Bug 215079 - Need platform support for H2 database
Summary: Need platform support for H2 database
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 enhancement with 14 votes (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL:
Whiteboard: submitted_patch
Keywords: api
Depends on:
Blocks:
 
Reported: 2008-01-11 15:14 EST by Michael Keith CLA
Modified: 2022-06-09 10:28 EDT (History)
11 users (show)

See Also:
peter.krogh: iplog+


Attachments
Compiled version of jar - see readme.txt in the jar (6.05 KB, application/x-zip-compressed)
2008-12-10 11:33 EST, Tom Ware CLA
no flags Details
H2Platform and test/core fixes (77.54 KB, patch)
2009-10-21 13:53 EDT, James Sutherland CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Keith CLA 2008-01-11 15:14:33 EST
We currently do not have an H2 database platform. This database is used by some people and they have asked for this support.
Comment 1 Michael Seidel CLA 2008-07-13 01:50:56 EDT
Please review the code and feel free to add it in the next release.

One think I don't understand is why the strategy in @Generated annotation
is ignored. The following is ignored, if the platform supports identity.

@GeneratedValue(strategy=GenerationType.SEQUENCE)

Identity is used instead. If I disable identity in the platform class
(supportsIdentity() returning false), a global sequence is used as expected.

Regards,
Michael
------------------------------------------------------------------------
public class H2Platform extends HSQLPlatform {
   private static final long serialVersionUID = -2935483687958482934L;

   public H2Platform() {
      super();
      setPingSQL("SELECT 1");
      setSupportsAutoCommit(true);
   }

   @Override
   public final boolean isHSQL() {
      return false;
   }

   @Override
   public void printSQLSelectStatement(DatabaseCall call, ExpressionSQLPrinter printer, SQLSelectStatement statement) {
      super.printSQLSelectStatement(call, printer, statement);
      ReadQuery query = statement.getQuery();
      if(query != null && query.isReadQuery() && !query.isUserDefined() && !query.isCallQuery()) {
         int firstRow = query.getFirstResult();
         int maxRows = query.getMaxRows();
         if(maxRows > 0 || firstRow > 0) {
            printer.printString(" LIMIT ");
            if(maxRows > 0) {
               maxRows -= firstRow;
            }
            else {
               // h2 syntax for limit clause requires max value (offset without limit is not possible)
               maxRows = Integer.MAX_VALUE;
            }
            printer.printPrimitive(maxRows);
            if(firstRow > 0) {
               printer.printString(" OFFSET ");
               printer.printPrimitive(firstRow);
            }
            call.setIgnoreFirstRowMaxResultsSettings(true);
         }
      }
   }

   @Override
   @SuppressWarnings("unchecked")
   protected Hashtable buildFieldTypes() {
      Hashtable fieldTypeMapping = super.buildFieldTypes();
      fieldTypeMapping.put(java.sql.Date.class, new FieldTypeDefinition("DATE", false));
      fieldTypeMapping.put(java.sql.Time.class, new FieldTypeDefinition("TIME", false));
      fieldTypeMapping.put(java.sql.Timestamp.class, new FieldTypeDefinition("TIMESTAMP", false));
      return fieldTypeMapping;
   }

   @Override
   public boolean isAlterSequenceObjectSupported() {
      return true;
   }

   @Override
   public ValueReadQuery buildSelectQueryForSequenceObject(String seqName, Integer size) {
      return new ValueReadQuery(new StringBuilder(20 + seqName.length()).append("CALL NEXT VALUE FOR ").append(seqName).toString());
   }

   @Override
   public Writer buildSequenceObjectAlterIncrementWriter(Writer writer, String fullSeqName, int increment) throws IOException {
      return writer.append("ALTER SEQUENCE ").append(fullSeqName).append(" INCREMENT BY ").append(Integer.toString(increment));
   }

   @Override
   public Writer buildSequenceObjectCreationWriter(Writer writer, String fullSeqName, int increment, int start) throws IOException {
      return writer.append("CREATE SEQUENCE IF NOT EXISTS ").append(fullSeqName).append(" START WITH ").append(Integer.toString(start))
            .append(" INCREMENT BY ").append(Integer.toString(increment));
   }

   @Override
   protected Sequence createPlatformDefaultSequence() {
      return new NativeSequence();
   }

   @Override
   public boolean supportsIdentity() {
      return true;
   }

   @Override
   public ValueReadQuery buildSelectQueryForIdentity() {
      return new ValueReadQuery("CALL IDENTITY()");
   }

   @Override
   public void printFieldIdentityClause(Writer writer) throws ValidationException {
      try {
         writer.append(" IDENTITY");
      }
      catch(IOException e) {
         throw ValidationException.logIOError(e);
      }
   }

   @Override
   public boolean supportsForeignKeyConstraints() {
      return true;
   }

   @Override
   public boolean supportsLocalTempTables() {
      return true;
   }

   @Override
   public boolean supportsGlobalTempTables() {
      return true;
   }

   @Override
   protected String getCreateTempTableSqlPrefix() {
      return "CREATE TEMPORARY TABLE IF NOT EXISTS ";
   }

   @Override
   public boolean supportsNativeSequenceNumbers() {
      return true;
   }

   @Override
   public boolean supportsStoredFunctions() {
      return true;
   }

   @Override
   public ValueReadQuery getTimestampQuery() {
      return new ValueReadQuery("SELECT CURRENT_TIMESTAMP()");
   }

   @Override
   protected void initializePlatformOperators() {
      super.initializePlatformOperators();
      addOperator(ExpressionOperator.simpleMath(ExpressionOperator.Concat, "||"));
   }
}
Comment 2 Michael Seidel CLA 2008-07-13 01:53:59 EDT
Perhaps, code was tested using the Geodata example. 
Comment 3 Thomas Mueller CLA 2008-11-10 16:04:57 EST
This class looks good. Please tell me if there is a problem,
I know the H2 code base quite well. 

Regards, Thomas
Comment 4 Tom Ware CLA 2008-12-10 11:33:21 EST
Created attachment 120068 [details]
Compiled version of jar - see readme.txt in the jar
Comment 5 Tom Ware CLA 2008-12-10 11:52:27 EST
Moving to the incubator component and making this platform available through through our Incubation page. (compiled version is availble here and an SVN version will be available soon in our incubator component)

See http://wiki.eclipse.org/EclipseLink/Development/Incubation for more info
Comment 6 Tom Ware CLA 2008-12-10 14:59:38 EST
See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=258347
Comment 7 Mike Kienenberger CLA 2009-04-24 18:58:33 EDT
The current H2Platform doesn't support sequences, only identity, for primary key generation under EclipseLink 1.0.2.   Having supportsSequenceObjects() return true fixes the problem.


### Eclipse Workspace Patch 1.0
#P cis
Index: H2Platform.java
===================================================================
RCS file: H2Platform.java,v
retrieving revision 1.1
diff -u -r1.1 H2Platform.java
--- H2Platform.java	21 Apr 2009 22:17:50 -0000	1.1
+++ H2Platform.java	24 Apr 2009 21:20:53 -0000
@@ -108,6 +108,10 @@
         return new NativeSequence();
     }
 
+    public boolean supportsSequenceObjects() {
+        return true;
+    }
+
     @Override
     public boolean supportsIdentity() {
         return true;
Comment 8 Tom Ware CLA 2009-09-03 14:56:39 EDT
Added to extensions incubator:

http://wiki.eclipse.org/EclipseLink/Development/Incubator/Extensions/H2Platform
Comment 9 James Sutherland CLA 2009-10-21 13:52:23 EDT
Adding platform to main stream.

Ran foundation LRG and JPA LRG, got all tests passing, except one failure in JPA because of a known bug in shared embeddables with sequencing.

Made several test fixes and H2 platform fixes.
Comment 10 James Sutherland CLA 2009-10-21 13:53:44 EDT
Created attachment 150137 [details]
H2Platform and test/core fixes
Comment 11 James Sutherland CLA 2009-10-21 14:07:19 EDT
SVN main commit: Bug#215079 - H2Platform

Passes foundation LRG, JPA LRG using new H2Platform.

Changes:
- Added H2Platform, with identity, sequencing, pagination, temp table, functions support.
- Exclude no_wait tests from H2 as no no_wait support.
- Add test browser login support for H2.
- Fixed some Oracle specific function expression tests.
- Various test fixes for identity sequencing, and query order.
- Exclude OrderedList varchar test from H2, as cannot auto convert varchar to number.
- Fixed close issue in emulated drivers.
- Various test fixes.
- Added new "eclipselink.jdbc.sql-cast" persistence property to disable CAST operation in DB2, Derby, Timesten as normally not required (still on by default).
- Added row argument to writeParameterMarker.
- Moved sequence creation code up, as common for most platforms.
- Added ifNull function, as was missing for most platforms.
- Removed logging being turned on in some tests.
- Resolve :param=:param test on casting platforms by setting query hint.
- Fixed weaver test API change.
Comment 12 Laird Nelson CLA 2009-11-23 14:38:04 EST
Would you consider backporting this fix?  I cannot yet move to 2.0.
Comment 13 Tom Ware CLA 2009-11-23 15:23:21 EST
It should be fairly easy to take the source for the new platform and use it in earlier versions of EclipseLink.

All you need is to grab the source, compile it against the earlier EclipseLink version and enable it using:

http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#Using_EclipseLink_JPA_Extensions_for_Session.2C_Target_Database_and_Target_Application_Server

You are looking for the eclipselink.target-database target.

If there are any issues with the compile it should be pretty easy to help you solve them on the mailing lists.
Comment 14 Eclipse Webmaster CLA 2022-06-09 10:28:20 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink