Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid MySQL schema generated when used with Connector/J 8.0.30 #446

Closed
nscuro opened this issue Aug 28, 2022 · 2 comments · Fixed by #447
Closed

Invalid MySQL schema generated when used with Connector/J 8.0.30 #446

nscuro opened this issue Aug 28, 2022 · 2 comments · Fixed by #447

Comments

@nscuro
Copy link
Contributor

nscuro commented Aug 28, 2022

Bug Report

DataNucleus RDBMS 6.0.1 generates an invalid schema for MySQL, when Connector/J 8.0.30 is used.

With 8.0.29, DataNucleus generates the following:

-- ----------------------------------------------------------------
-- DataNucleus SchemaTool (ran at 28/08/2022 22:09:16)
-- ----------------------------------------------------------------
-- Complete schema required for the following classes:-
--     mydomain.model.Person
--
-- Table "PERSON" for classes [mydomain.model.Person]
CREATE TABLE "PERSON"
(
    "ID" BIGINT NOT NULL,
    "NAME" VARCHAR(255) BINARY NULL,
    CONSTRAINT "PERSON_PK" PRIMARY KEY ("ID")
) ENGINE=INNODB;

With 8.0.30, the type of "NAME" changes to TINYTEXT(255):

-- ----------------------------------------------------------------
-- DataNucleus SchemaTool (ran at 28/08/2022 21:26:53)
-- ----------------------------------------------------------------
-- Complete schema required for the following classes:-
--     mydomain.model.Person
--
-- Table "PERSON" for classes [mydomain.model.Person]
CREATE TABLE "PERSON"
(
    "ID" BIGINT NOT NULL,
    "NAME" TINYTEXT(255) NULL,
    CONSTRAINT "PERSON_PK" PRIMARY KEY ("ID")
) ENGINE=INNODB;

The TINYTEXT type does not accept a length argument, causing the generated schema to be invalid.

I didn't spot anything obvious in the Connector/J changelogs that could explain this behavior.

Test Case

I've put together a test setup to reproduce this here: https://github.com/nscuro/datanucleus-test-jdo/tree/rdbms-issue-446

  • start-database.sh launches a MySQL 5.7 database with Docker
  • generate-schema.sh uses the DN SchemaTool to generate the complete schema and write it to schema.sql
@andyjefferson
Copy link
Member

The only thing different is the JDBC driver, so the JDBC driver has changed its support for some JDBC/SQL type. Using schematool "dbinfo" would tell you where the problem is.

@nscuro
Copy link
Contributor Author

nscuro commented Aug 29, 2022

You're right, the default for the VARCHAR type has changed from VARCHAR(M) BINARY to TINYTEXT:

JDBC Type=VARCHAR sqlTypes=VARCHAR(M) BINARY,TINYTEXT (default=VARCHAR(M) BINARY)
    SQLTypeInfo : [JDBC-DRIVER]
      type : name = VARCHAR(M) BINARY, jdbcId = 12, localName = VARCHAR, createParams = 
      precision = 65535, allowsSpec = true, numPrecRadix = 10
      scale : min = 0, max = 0, fixedPrec = false
      literals : prefix = ', suffix = '
      nullable = 1, caseSensitive = true, searchable = 3, unsigned = false, autoIncrement = false

    SQLTypeInfo : [JDBC-DRIVER]
      type : name = TINYTEXT, jdbcId = 12, localName = TINYTEXT, createParams =  [CHARACTER SET charset_name] [COLLATE collation_name]
      precision = 255, allowsSpec = true, numPrecRadix = 10
      scale : min = 0, max = 0, fixedPrec = false
      literals : prefix = ', suffix = '
      nullable = 1, caseSensitive = true, searchable = 3, unsigned = false, autoIncrement = false
JDBC Type=VARCHAR sqlTypes=VARCHAR(M) BINARY,TINYTEXT (default=TINYTEXT)
    SQLTypeInfo : [JDBC-DRIVER]
      type : name = VARCHAR(M) BINARY, jdbcId = 12, localName = VARCHAR, createParams = 
      precision = 65535, allowsSpec = true, numPrecRadix = 10
      scale : min = 0, max = 0, fixedPrec = false
      literals : prefix = ', suffix = '
      nullable = 1, caseSensitive = true, searchable = 3, unsigned = false, autoIncrement = false

    SQLTypeInfo : [JDBC-DRIVER]
      type : name = TINYTEXT, jdbcId = 12, localName = TINYTEXT, createParams =  [CHARACTER SET charset_name] [COLLATE collation_name]
      precision = 255, allowsSpec = true, numPrecRadix = 10
      scale : min = 0, max = 0, fixedPrec = false
      literals : prefix = ', suffix = '
      nullable = 1, caseSensitive = true, searchable = 3, unsigned = false, autoIncrement = false

And it looks like TINYTEXT is reported as supporting a precision specification (allowsSpec = true), despite not actually doing so. Looking at the DN codebase, this seems to be a common issue with MySQL:

private void fixAllowsPrecisionSpec()
{
if (typeName.equalsIgnoreCase("LONG VARCHAR") ||
typeName.equalsIgnoreCase("BLOB") ||
typeName.equalsIgnoreCase("MEDIUMBLOB") ||
typeName.equalsIgnoreCase("LONGBLOB") ||
typeName.equalsIgnoreCase("MEDIUMTEXT") ||
typeName.equalsIgnoreCase("LONGTEXT") ||
typeName.equalsIgnoreCase("TEXT"))
{
// Some MySQL types don't allow precision specification i.e "LONG VARCHAR(...)" is illegal
allowsPrecisionSpec = false;
}
}

I raised a PR in #447 and verified that it fixes the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants