On Tue, 13 Oct 2026 at 13:51, Richard Zowalla <[email protected]> wrote:
>
> Hi Maxim,
>
> The substitution is the right idea, but I would not put it in MappingTool.
>
> addSequenceComponents only runs during schema tooling. It works at runtime 
> only because it mutates the shared SequenceMetaData, so the rewritten plugin 
> happens to stick if the same repository is used afterwards.
> Without the tool — a plain EMF against an existing schema — a named 
> @SequenceGenerator still reaches NativeJDBCSeq and fails with the same 
> message.
> Rewriting metadata as a side effect of tooling also assumes the tool's 
> dictionary is the runtime's.
>
> Imho it belongs where the sequence is resolved, i.e. SequenceMapping / 
> MappingRepository. Then both the tool and the runtime see it and MappingTool 
> needs no change.
>
> I can sketch up an implementation under OPENJPA-3001 too, if you would prefer 
> that way

yes please :)
you can use to the `tck-mysql` branch or create the new one :)

>
> Gruß
> Richard
>
> > Am 12.10.2026 um 07:10 schrieb Maxim Solodovnik <[email protected]>:
> >
> > I've modified MappingTool as follows [1]
> > Do you feel it worth committing? :)
> >
> > so tests still failing due to there are methods like this:
> >
> > protected void createSequenceGenerator() {
> >    try {
> >        getEntityTransaction().begin();
> >        getEntityManager().createNativeQuery("CREATE SEQUENCE
> > SEQGENERATOR START WITH 10").executeUpdate();
> >        getEntityTransaction().commit();
> >    } catch (Exception e) {
> >        logger.log(Logger.Level.ERROR, "Exception encountered while
> > creating seq:", e);
> >    }
> > }
> >
> > not sure how it should work ....
> >
> > [1]
> > diff --git 
> > a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingTool.java
> > b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingTool.java
> > index 91c769ade..aeff3bf62 100644
> > --- 
> > a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingTool.java
> > +++ 
> > b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingTool.java
> > @@ -738,30 +738,39 @@ public class MappingTool
> >         SchemaGroup group) {
> >         SequenceMetaData smd = mapping.getIdentitySequenceMetaData();
> >         Seq seq = null;
> > -        if (smd != null)
> > +        if (smd != null) {
> >             seq = smd.getInstance(null);
> > -        else if (mapping.getIdentityStrategy() == ValueStrategies.NATIVE
> > +        } else if (mapping.getIdentityStrategy() == ValueStrategies.NATIVE
> >             || (mapping.getIdentityStrategy() == ValueStrategies.NONE
> >             && mapping.getIdentityType() == ClassMetaData.ID_DATASTORE))
> > +        {
> >             seq = _conf.getSequenceInstance();
> > +        }
> >
> > -        if (seq instanceof JDBCSeq)
> > -            ((JDBCSeq) seq).addSchema(mapping, group);
> > +        if (seq instanceof JDBCSeq jdbcSeq) {
> > +            jdbcSeq.addSchema(mapping, group);
> > +        }
> >
> >         FieldMapping[] fmds;
> > -        if (mapping.getEmbeddingMetaData() == null)
> > +        if (mapping.getEmbeddingMetaData() == null) {
> >             fmds = mapping.getDefinedFieldMappings();
> > -        else
> > +        } else {
> >             fmds = mapping.getFieldMappings();
> > +        }
> >         for (FieldMapping fmd : fmds) {
> >             smd = fmd.getValueSequenceMetaData();
> >             if (smd != null) {
> > +                if
> > (SequenceMetaData.IMPL_NATIVE.equals(smd.getSequencePlugin()) &&
> > _dict.nextSequenceQuery == null) {
> > +                    _log.warn(_loc.get("no-seq-sql", smd.getSequence()));
> > +                    smd.setSequencePlugin(SequenceMapping.IMPL_TABLE);
> > +                }
> >                 seq = smd.getInstance(_loader);
> > -                if (seq instanceof JDBCSeq)
> > -                    ((JDBCSeq) seq).addSchema(mapping, group);
> > -            }
> > -            else if (fmd.getEmbeddedMapping() != null)
> > +                if (seq instanceof JDBCSeq jdbcSeq) {
> > +                    jdbcSeq.addSchema(mapping, group);
> > +                }
> > +            } else if (fmd.getEmbeddedMapping() != null) {
> >                 addSequenceComponents(fmd.getEmbeddedMapping(), group);
> > +            }
> >         }
> >     }
> >
> >
> > On Fri, 9 Oct 2026 at 16:09, Maxim Solodovnik <[email protected]> wrote:
> >>
> >> Hello Richard,
> >>
> >> On Fri, 9 Oct 2026 at 14:58, Richard Zowalla <[email protected]> wrote:
> >>>
> >>> Hi Maxim,
> >>>
> >>> Good news: no emulation needed, and no growing table either.
> >>>
> >>> Neither MySQLDictionary nor MariaDBDictionary sets nextSequenceQuery, so 
> >>> NativeJDBCSeq.endConfiguration() throws for any @SequenceGenerator. But 
> >>> OpenJPA already ships a table-backed sequence: SequenceMapping.IMPL_TABLE 
> >>> / IMPL_VALUE_TABLE, implemented by TableJDBCSeq, which keeps a single row 
> >>> per sequence in OPENJPA_SEQUENCE_TABLE (column SEQUENCE_VALUE) and 
> >>> updates it in place. That is the same approach Hibernate and EclipseLink 
> >>> take on MySQL, so AUTO_INCREMENT is not required and nothing grows.
> >>>
> >>> I would split it in two, because the two dbms are different:
> >>>
> >>> MariaDB can do it natively. MariaDB 10.3 and later has real sequence 
> >>> objects (CREATE SEQUENCE, NEXT VALUE FOR seq, NEXTVAL(seq)), and you are 
> >>> running 11.8. So MariaDBDictionary.connectedConfiguration() can set 
> >>> nextSequenceQuery once the server reports >= 10.3, following the 
> >>> version-gated pattern PostgresDictionary already uses for 
> >>> storeCharsAsNumbers, and leave the older versions alone. That should make 
> >>> the sequence TCK tests pass on MariaDB without any mapping change.
> >>>
> >>> MySQL has no sequences at any version, so a @SequenceGenerator has to 
> >>> fall back to the table sequence. Interestingly part of it is already 
> >>> there: AnnotationPersistenceMetaDataParser does both GenerationType.TABLE 
> >>> and GenerationType.SEQUENCE through the system openjpa.Sequence setting 
> >>> when the generator is unnamed. The gap would be a named generator on a 
> >>> dictionary without native sequences, which currently fails instead of 
> >>> falling back.
> >>>
> >>> As a workaround for your branch right now, before any code change, you 
> >>> can point the named generator at the table implementation, e.g.
> >>>
> >>> openjpa.Sequence: table(Table=OPENJPA_SEQUENCE_TABLE)
> >>
> >> this would be hard to implement for TCK :(
> >> we do pass params via
> >> <jpa.provider.implementation.specific.properties> which has `:`
> >> delimiter
> >> but inside the key it has `=` delimiter :(
> >>
> >> and we already passing `openjpa.Sequence=time` ....
> >>
> >> so the only options are: System property and code modification :)
> >> I'll try to modify the code
> >>
> >>>
> >>> for the unnamed case, or give the generator an explicit table 
> >>> implementation in the mapping.
> >>>
> >>> The MariaDB version check would be low risk, the MySQL fallback changes 
> >>> identity generation behaviour on a database people are using, so I would 
> >>> keep them as separate commits (and probably separate review) even if they 
> >>> share one issue.
> >>>
> >>> Hope it helps
> >>> Richard
> >>>
> >>>
> >>>> Am 09.10.2026 um 05:45 schrieb Maxim Solodovnik <[email protected]>:
> >>>>
> >>>> There is great progress :))
> >>>> Failing list is reduced :))
> >>>>
> >>>> Some tests are failing due to:
> >>>>
> >>>> ```
> >>>> SEVERE: Exception encountered while creating seq:
> >>>> <openjpa-4.2.0-SNAPSHOT-r832b5cdM fatal user error>
> >>>> org.apache.openjpa.persistence.ArgumentException: Error instantiating
> >>>> named sequence "SEQGENERATOR": Your database dictionary does not
> >>>> support native sequences.  To tell the dictionary how to select
> >>>> sequence values, use:
> >>>> openjpa.jdbc.DBDictionary: NextSequenceQuery="SELECT NEXT VALUE FOR
> >>>> "SEQGENERATOR"
> >>>> Where the above string is replaced with the proper SQL for your database.
> >>>> at 
> >>>> org.apache.openjpa.jdbc.kernel.NativeJDBCSeq.endConfiguration(NativeJDBCSeq.java:190)
> >>>> ```
> >>>>
> >>>> I guess SEQUENCE can be emulated with AUTOINCREMENT
> >>>> https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html
> >>>> But having growing table seems to be overkill ....
> >>>>
> >>>> On Thu, 8 Oct 2026 at 21:08, Maxim Solodovnik <[email protected]> 
> >>>> wrote:
> >>>>>
> >>>>> It seems regular MySql tests are broken :(
> >>>>>
> >>>>> ```
> >>>>> [ERROR] Failures:
> >>>>> [ERROR]   
> >>>>> TestContainerSpecCompatibilityOptions>AbstractPersistenceTestCase.run:213->AbstractPersistenceTestCase.runBare:553->AbstractPersistenceTestCase.runBare:577->AbstractPersistenceTestCase.runTest:590->testLegacyDefaultMapKeyColumnName:471->assertSQLFragnments:932
> >>>>> None of the following 3 SQL
> >>>>> [ERROR]   
> >>>>> TestBiDirectionalJoinTable>AbstractPersistenceTestCase.run:213->AbstractPersistenceTestCase.runBare:553->AbstractPersistenceTestCase.runBare:577->AbstractPersistenceTestCase.runTest:590->testBulkDelete:138->SQLListenerTestCase.assertSQL:74
> >>>>> Expected regular expression
> >>>>> [ERROR]   
> >>>>> TestBulkDeleteCompositeId>AbstractPersistenceTestCase.run:213->AbstractPersistenceTestCase.runBare:553->AbstractPersistenceTestCase.runBare:577->AbstractPersistenceTestCase.runTest:590->testCompositeKeyCandidateWithoutCriteria:65->SQLListenerTestCase.assertSQL:74
> >>>>> Expected regular expression
> >>>>> [ERROR]   
> >>>>> TestBulkDeleteDependentFields>AbstractPersistenceTestCase.run:213->AbstractPersistenceTestCase.runBare:553->AbstractPersistenceTestCase.runBare:577->AbstractPersistenceTestCase.runTest:590->testUnfilteredDeleteCleansOwnedTablesOfDependentFields:140->SQLListenerTestCase.assertSQL:74
> >>>>> Expected regular
> >>>>> [ERROR]   
> >>>>> TestBulkDeleteJoinTable>AbstractPersistenceTestCase.run:213->AbstractPersistenceTestCase.runBare:553->AbstractPersistenceTestCase.runBare:577->AbstractPersistenceTestCase.runTest:590->testBulkDeleteWithoutCriteriaEmptiesOwnedTables:58->SQLListenerTestCase.assertSQL:74
> >>>>> Expected regular expression
> >>>>> [ERROR]   
> >>>>> TestBulkDeleteSubclassJoinTable>AbstractPersistenceTestCase.run:213->AbstractPersistenceTestCase.runBare:553->AbstractPersistenceTestCase.runBare:577->AbstractPersistenceTestCase.runTest:590->testBulkDeleteThroughBaseClass:51->SQLListenerTestCase.assertSQL:74
> >>>>> Expected regular expression
> >>>>>
> >>>>> [INFO] OpenJPA Persistence JDBC ........................... FAILURE [  
> >>>>> 01:33 h]
> >>>>>
> >>>>> [ERROR] Tests run: 3761, Failures: 6, Errors: 0, Skipped: 0
> >>>>> ```
> >>>>>
> >>>>> On Thu, 8 Oct 2026 at 13:37, Maxim Solodovnik <[email protected]> 
> >>>>> wrote:
> >>>>>>
> >>>>>> Hello Richard,
> >>>>>>
> >>>>>> On Thu, 8 Oct 2026 at 13:24, Richard Zowalla <[email protected]> wrote:
> >>>>>>>
> >>>>>>> Hi Maxim,
> >>>>>>>
> >>>>>>> the truncation is a consequence of it, not a separate problem.
> >>>>>>>
> >>>>>>> DBDictionary.storeCharsAsNumbers still defaults to true 
> >>>>>>> (DBDictionary:327), and only DB2 (DB2Dictionary:124) and PostgreSQL 
> >>>>>>> (PostgresDictionary:151) switch it off.
> >>>>>>> MySQL inherits the legacy default, so:
> >>>>>>>
> >>>>>>> - getPreferredType() maps JavaTypes.CHAR to Types.INTEGER 
> >>>>>>> (DBDictionary:2006) — that is the "Given column: Type: integer" in 
> >>>>>>> your warning, and
> >>>>>>> - setChar() takes the numeric branch because the mapped column 
> >>>>>>> reports as INTEGER-compatible (DBDictionary:1285) and does 
> >>>>>>> setInt(stmnt, idx, (int) val).
> >>>>>>>
> >>>>>>> So for
> >>>>>>>
> >>>>>>> @Column(name = "CHARDATA")
> >>>>>>> protected char characterData;
> >>>>>>>
> >>>>>>> we send 65 into the TCK's CHARDATA CHAR column, and two digits do not 
> >>>>>>> fit one character: code 1406, "Data too long for column 'CHARDATA'".
> >>>>>>>
> >>>>>>> Workaround for your branch, no code change needed:
> >>>>>>>
> >>>>>>> openjpa.jdbc.DBDictionary=mysql(StoreCharsAsNumbers=false)
> >>>>>>>
> >>>>>>> However, I would fix it the way we did for PostgreSQL in 
> >>>>>>> OPENJPA-2971: have MySQLDictionary set storeCharsAsNumbers = false in 
> >>>>>>> the constructor, keep the isStoreCharsAsNumbersExplicit()
> >>>>>>> so a value a user set explicitly is never overwritten, and add a 
> >>>>>>> migration note — existing MySQL schemas created by earlier OpenJPA 
> >>>>>>> releases have INTEGER columns for
> >>>>>>> char fields and will need StoreCharsAsNumbers=true to keep working.
> >>>>>>
> >>>>>> I'll give it a try and will write back :)
> >>>>>> Thanks a million for your help! :)
> >>>>>>
> >>>>>>>
> >>>>>>> That is exactl  OPENJPA-3001.
> >>>>>>>
> >>>>>>> On the schema generation: drop-and-create cannot help here, and the 
> >>>>>>> error you get comes from a different place.
> >>>>>>> "Table ... has a foreign key to table ... that has not been 
> >>>>>>> generated" is thrown by SchemaGenerator:885 while reading the
> >>>>>>> live database metadata; it fires when a foreign key in the existing 
> >>>>>>> schema points at a table that is not part of the group being 
> >>>>>>> generated.
> >>>>>>>
> >>>>>>> With leftover tables from other TCK persistence units in the same 
> >>>>>>> database, any subset run trips it.
> >>>>>>>
> >>>>>>> Since the TCK ships its own DDL, I would not let OpenJPA generate the 
> >>>>>>> schema for a TCK run at all.
> >>>>>>> A clean database per run (DROP DATABASE / CREATE DATABASE, or a 
> >>>>>>> schema per PU) is more reliable
> >>>>>>> than asking the schema tool to reconcile. Once the column type is 
> >>>>>>> right, the incompatibility warning and the truncation, should 
> >>>>>>> disappear.
> >>>>>>
> >>>>>> Actually current script drops all local data at docker stop
> >>>>>> https://github.com/apache/openjpa/commit/db9c64be252643555803988f3330d8b32a09dd5a
> >>>>>> ```
> >>>>>>                           <keepContainer>false</keepContainer>
> >>>>>>                           <removeVolumes>true</removeVolumes>
> >>>>>> ```
> >>>>>>
> >>>>>>>
> >>>>>>> Best regards,
> >>>>>>> Richard
> >>>>>>>
> >>>>>>> On 2026-10-07 06:10 UTC Maxim Solodovnik wrote:
> >>>>>>>> Hello All,
> >>>>>>>>
> >>>>>>>> I'm trying to investigate TCK failures with Mysql DB
> >>>>>>>>
> >>>>>>>> I'm investigating 'Data truncation: Data too long for column' class 
> >>>>>>>> of problems
> >>>>>>>> I've notices these errors are coupled with warnings like:
> >>>>>>>> ```
> >>>>>>>> 19  WARN   [main] openjpa.jdbc.Schema - Existing column "CHARDATA" on
> >>>>>>>> table "DATATYPES" is incompatible with the same column in the given
> >>>>>>>> schema definition. Existing column:
> >>>>>>>> Full Name: DATATYPES.CHARDATA
> >>>>>>>> Type: char
> >>>>>>>> Size: 1
> >>>>>>>> Default: null
> >>>>>>>> Not Null: false
> >>>>>>>> Given column:
> >>>>>>>> Full Name: DATATYPES.CHARDATA
> >>>>>>>> Type: integer
> >>>>>>>> Size: 0
> >>>>>>>> Default: null
> >>>>>>>> Not Null: false
> >>>>>>>> ```
> >>>>>>>>
> >>>>>>>> So my guess was: schemaTool need to be instructed to drop/create
> >>>>>>>> existing table so column definition will be updated to have correct
> >>>>>>>> type
> >>>>>>>>
> >>>>>>>> I've tried to add
> >>>>>>>> `jakarta.persistence.schema-generation.database.action=drop-and-create`
> >>>>>>>> (as well as 
> >>>>>>>> `:jakarta.persistence.schema-generation.database.action=drop-and-create:jakarta.persistence.schema-generation.scripts.action=drop-and-create`)
> >>>>>>>>
> >>>>>>>> But got `Table "{0}" has a foreign key to table "{1}" that has not 
> >>>>>>>> been \
> >>>>>>>> generated.  You must run the schema generator on all inter-related 
> >>>>>>>> tables \
> >>>>>>>> at once.` errors instead :(
> >>>>>>>>
> >>>>>>>> Any help is appreciated :)))
> >>>>>>>>
> >>>>>>>> I'm playing at `tck-mysql` branch :))
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> --
> >>>>>>>> Best regards,
> >>>>>>>> Maxim
> >>>>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> --
> >>>>>> Best regards,
> >>>>>> Maxim
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> Best regards,
> >>>>> Maxim
> >>>>
> >>>>
> >>>>
> >>>> --
> >>>> Best regards,
> >>>> Maxim
> >>>
> >>
> >>
> >> --
> >> Best regards,
> >> Maxim
> >
> >
> >
> > --
> > Best regards,
> > Maxim
>


-- 
Best regards,
Maxim

Reply via email to