[MDEV-27498] Incorrect string value: '\xF4\x80\x80\x83 for character set utf8mb4 Created: 2022-01-14  Updated: 2022-01-24  Resolved: 2022-01-24

Status: Closed
Project: MariaDB Server
Component/s: Character Sets, Data Manipulation - Insert
Affects Version/s: 10.6.5
Fix Version/s: N/A

Type: Bug Priority: Major
Reporter: Karsten Budde Assignee: Alexander Barkov
Resolution: Not a Bug Votes: 0
Labels: utf8mb4
Environment:

CentOS



 Description   

Hello,

when inserting a Unicode text into a longtext database field, I get the error message for the character F4808083:

System.Exception: SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect string value: '\xF4\x80\x80\x83 f...' for column `hzowork`.`document`.`dataContent` at row 1

According to my research on the Internet, the Unicode character F4808083 is within the allowed range of Unicode according to RFC3629.

Does the utf8mb4 character set not map the entire valid range according to RFC3629?

With kind regards
Karsten



 Comments   
Comment by Daniel Black [ 2022-01-14 ]

why is it saying datetime format? What does show create table hzowork.document show for dataContent?

Comment by Karsten Budde [ 2022-01-14 ]

here is the table definition:

CREATE TABLE `document` (
  `clientId` int(10) unsigned NOT NULL COMMENT 'Id des Mandanten',
  `documentType` int(10) unsigned NOT NULL COMMENT 'ItemId der Dokumentart',
  `obId` int(10) unsigned NOT NULL COMMENT 'Id des Objektes,zu dem die Zusatzinformation gehört',
  `locale` varchar(15) CHARACTER SET utf8mb3 NOT NULL COMMENT 'Angabe zur Sprache in der Spalte content, mögliche Werte: de_DE, de_AT, de_CH, fr_CH, ...',
  `variantNo` int(10) NOT NULL DEFAULT 1000 COMMENT 'Variante zur defId: 1000 (Original), ...  \r\nWelche Varianten pro defId möglich sind, ist in den Definitionsdaten beschrieben.',
  `obDefId` int(10) unsigned NOT NULL COMMENT 'Typdefinition zur obId',
  `obOwnerId` int(10) unsigned NOT NULL COMMENT 'ownerId aus der Objekttabelle zur obId',
  `dataContent` longtext CHARACTER SET utf8mb3 NOT NULL COMMENT 'textueller Inhalt',
  `searchContent` longtext DEFAULT NULL COMMENT 'Inhalt aus dataContent normalisiert für die Volltextsuche',
  `checksumList` text DEFAULT NULL COMMENT 'Liste zusätzlicher Checksummen für die Ähnlichkeitsberechung',
  `characters` int(10) unsigned NOT NULL COMMENT 'Anzahl der Zeichen',
  `workStatus` char(1) CHARACTER SET utf8mb3 NOT NULL DEFAULT 'N' COMMENT 'Bearbeitungszustand - mögliche Werte: \r\nN - neu \r\nB - in Bearbeitung \r\nU - unverändert seit letzter Lieferung \r\nL - zur Lieferung gemeldet ',
  `deliveryDate` datetime(6) DEFAULT NULL COMMENT 'Datum der letzten Lieferung der Daten',
  `deleteFlag` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Löschkennzeichen - mögliche Werte: \r\n0 - ungelöscht \r\n>0 - gelöscht  \r\nEin gelöschter Datensatz wird nirgendwo mehr angezeigt und kann auch nicht mehr bearbeitet werden. ',
  `deleteText` varchar(255) CHARACTER SET utf8mb3 DEFAULT NULL COMMENT 'Erläuterung, warum die Daten gelöscht wurden',
  `newDate` timestamp(6) NOT NULL DEFAULT current_timestamp(6) COMMENT 'Datum der Erzeugung',
  `newUserId` int(10) unsigned NOT NULL COMMENT 'Wer den Datensatz erzeugt hat',
  `changeDate` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6) COMMENT 'Änderungsdatum',
  `changeUserId` int(10) unsigned NOT NULL COMMENT 'Wer den Datensatz geändert hat',
  PRIMARY KEY (`documentType`,`obId`,`locale`,`variantNo`),
  UNIQUE KEY `clientIdDocumentTypeObIdLocaleVariantNo` (`clientId`,`documentType`,`obId`,`locale`,`variantNo`),
  KEY `clientId` (`clientId`,`obId`),
  CONSTRAINT `document_object_FK` FOREIGN KEY (`clientId`, `obId`) REFERENCES `object` (`clientId`, `id`),
  CONSTRAINT `jsonCheck` CHECK (`checksumList` is null or json_valid(`checksumList`))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Diese Tabelle enthält die Varianten der Dokumente.\r\nEs gibt mehrere Arten von Texten, die durch die Dokumentart festgelegt wird.\r\n\r\nUnterschied zwischen documentType und variantNo:\r\n- Verschiedene Dokumentarten können unterschiedliche Varianten haben.\r\n- Alle Varianten einer Dokumentart haben dieselbe Versionsnummer.\r\n- Alle Varianten > 1000 können inhaltlich von der Variante 1000 abgeleitet werden.\r\n- Unterschiedliche Dokumentarten können einzeln geliefert werden.\r\n- Zu einer Dokumentart werden alle Varianten gleichzeitig geliefert.\r\n- In der Regel werden die Varianten zur Variante 1000 per Software erzeugt.\r\n\r\nBeispiel für ein Objekt mit einer Dokumentart und 2 Varianten:\r\nDas Objekt einer VOB-Position hat die Dokumentart X mit dem Positionstext. \r\nDas Dokument gibt es in zwei Varianten: \r\nVariante A - XML-Format für die Bearbeitung im HzO,\r\nVariante B - GEAB-XML. \r\nDie Variante B wird durch Software aus der Variante A erzeugt.\r\n\r\nBeispiel für ein Objekt mit mehreren Dokumentarten mit jeweils nur einer Variante:\r\nDas Objekt einer News hat zwei Dokumentarten Y und Z. Y ist der Teaser für die Verwendung im Newsletter. Z ist der Text der News, die im Portal angezeigt wird. \r\nFür beide Texte gibt es nur die Variante 1000. Beide Texte können unterschiedlich geliefert werden.'

i don't know why the error message assumes that the string should be interpreted as a date format.

However, I also don't know why a different character set than the table's default character set was used in the columns when creating the document table.

I will now change the character set of the column to utf8mb4 and test again.

Comment by Marko Mäkelä [ 2022-01-14 ]

I do not think that this has anything to do with a particular storage engine.
But, I do see the following in your table declaration:

`dataContent` longtext CHARACTER SET utf8mb3 NOT NULL COMMENT 'textueller Inhalt',

The SQL layer appears to be correctly rejecting the utf8mb4 value for that column.

Comment by Karsten Budde [ 2022-01-17 ]

I have changed the column definitions to the utf8mb4 character set.

alter table document
 modify locale varchar(15) character set utf8mb4 not null comment 'Angabe zur Sprache in der Spalte content, mögliche Werte: de_DE, de_AT, de_CH, fr_CH, ...',
 modify dataContent longtext character set utf8mb4 not null comment 'ownerId aus der Objekttabelle zur obId',
 modify workStatus char(1) character set utf8mb4 not null DEFAULT 'N' COMMENT 'Bearbeitungszustand - mögliche Werte: \r\nN - neu \r\nB - in Bearbeitung \r\nU - unverändert seit letzter Lieferung \r\nL - zur Lieferung gemeldet ',
 modify deleteText varchar(255) character set utf8mb4 DEFAULT NULL COMMENT 'Erläuterung, warum die Daten gelöscht wurden'

Now the table definition is like this:

CREATE TABLE `document` (
  `clientId` int(10) unsigned NOT NULL COMMENT 'Id des Mandanten',
  `documentType` int(10) unsigned NOT NULL COMMENT 'ItemId der Dokumentart',
  `obId` int(10) unsigned NOT NULL COMMENT 'Id des Objektes,zu dem die Zusatzinformation gehört',
  `locale` varchar(15) NOT NULL COMMENT 'Angabe zur Sprache in der Spalte content, mögliche Werte: de_DE, de_AT, de_CH, fr_CH, ...',
  `variantNo` int(10) NOT NULL DEFAULT 1000 COMMENT 'Variante zur defId: 1000 (Original), ...  \r\nWelche Varianten pro defId möglich sind, ist in den Definitionsdaten beschrieben.',
  `obDefId` int(10) unsigned NOT NULL COMMENT 'Typdefinition zur obId',
  `obOwnerId` int(10) unsigned NOT NULL COMMENT 'ownerId aus der Objekttabelle zur obId',
  `dataContent` longtext NOT NULL COMMENT 'ownerId aus der Objekttabelle zur obId',
  `searchContent` longtext DEFAULT NULL COMMENT 'Inhalt aus dataContent normalisiert für die Volltextsuche',
  `checksumList` text DEFAULT NULL COMMENT 'Liste zusätzlicher Checksummen für die Ähnlichkeitsberechung',
  `characters` int(10) unsigned NOT NULL COMMENT 'Anzahl der Zeichen',
  `workStatus` char(1) NOT NULL DEFAULT 'N' COMMENT 'Bearbeitungszustand - mögliche Werte: \r\nN - neu \r\nB - in Bearbeitung \r\nU - unverändert seit letzter Lieferung \r\nL - zur Lieferung gemeldet ',
  `deliveryDate` datetime(6) DEFAULT NULL COMMENT 'Datum der letzten Lieferung der Daten',
  `deleteFlag` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Löschkennzeichen - mögliche Werte: \r\n0 - ungelöscht \r\n>0 - gelöscht  \r\nEin gelöschter Datensatz wird nirgendwo mehr angezeigt und kann auch nicht mehr bearbeitet werden. ',
  `deleteText` varchar(255) DEFAULT NULL COMMENT 'Erläuterung, warum die Daten gelöscht wurden',
  `newDate` timestamp(6) NOT NULL DEFAULT current_timestamp(6) COMMENT 'Datum der Erzeugung',
  `newUserId` int(10) unsigned NOT NULL COMMENT 'Wer den Datensatz erzeugt hat',
  `changeDate` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6) COMMENT 'Änderungsdatum',
  `changeUserId` int(10) unsigned NOT NULL COMMENT 'Wer den Datensatz geändert hat',
  PRIMARY KEY (`documentType`,`obId`,`locale`,`variantNo`),
  UNIQUE KEY `clientIdDocumentTypeObIdLocaleVariantNo` (`clientId`,`documentType`,`obId`,`locale`,`variantNo`),
  KEY `clientId` (`clientId`,`obId`),
  CONSTRAINT `document_object_FK` FOREIGN KEY (`clientId`, `obId`) REFERENCES `object` (`clientId`, `id`),
  CONSTRAINT `jsonCheck` CHECK (`checksumList` is null or json_valid(`checksumList`))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Diese Tabelle enthält die Varianten der Dokumente.\r\nEs gibt mehrere Arten von Texten, die durch die Dokumentart festgelegt wird.\r\n\r\nUnterschied zwischen documentType und variantNo:\r\n- Verschiedene Dokumentarten können unterschiedliche Varianten haben.\r\n- Alle Varianten einer Dokumentart haben dieselbe Versionsnummer.\r\n- Alle Varianten > 1000 können inhaltlich von der Variante 1000 abgeleitet werden.\r\n- Unterschiedliche Dokumentarten können einzeln geliefert werden.\r\n- Zu einer Dokumentart werden alle Varianten gleichzeitig geliefert.\r\n- In der Regel werden die Varianten zur Variante 1000 per Software erzeugt.\r\n\r\nBeispiel für ein Objekt mit einer Dokumentart und 2 Varianten:\r\nDas Objekt einer VOB-Position hat die Dokumentart X mit dem Positionstext. \r\nDas Dokument gibt es in zwei Varianten: \r\nVariante A - XML-Format für die Bearbeitung im HzO,\r\nVariante B - GEAB-XML. \r\nDie Variante B wird durch Software aus der Variante A erzeugt.\r\n\r\nBeispiel für ein Objekt mit mehreren Dokumentarten mit jeweils nur einer Variante:\r\nDas Objekt einer News hat zwei Dokumentarten Y und Z. Y ist der Teaser für die Verwendung im Newsletter. Z ist der Text der News, die im Portal angezeigt wird. \r\nFür beide Texte gibt es nur die Variante 1000. Beide Texte können unterschiedlich geliefert werden.'

The following test unfortunately brought the same error when inserting.

System.Exception: SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect string value: '\xF4\x80\x80\x83 f...' for column `hzowork`.`document`.`dataContent` at row 1

Comment by Marko Mäkelä [ 2022-01-17 ]

As far as I can tell, the UTF-8 byte sequence \xf4\x80\x80\x83 would represent the code point U+100003, which gucharmap on my system does not identify as a valid code point. But, it is less than the U+10FFFF, which I would expect to be the maximum representable code point in 4-byte UTF-8. I am not an expert in this; bar is.

Comment by Alexander Barkov [ 2022-01-18 ]

Please show the output of this command:

SHOW VARIABLES LIKE 'character_set%';

Possibly, the session character set is utf8mb3 rather than utf8mb4.

Comment by Karsten Budde [ 2022-01-18 ]

Thanks for the tip.

When I run the command in DBeaver, I get the following result:

Variable_name           |Value                     
------------------------+--------------------------
character_set_client    |utf8mb4                   
character_set_connection|utf8mb4                   
character_set_database  |utf8mb4                   
character_set_filesystem|binary                    
character_set_results   |utf8mb4                   
character_set_server    |utf8mb4                   
character_set_system    |utf8mb3                   
character_sets_dir      |/usr/share/mysql/charsets/

When the command is run in the application server under PHP, it gives the following result:

array(8) {
[0]=>
array(2) {
["Variable_name"]=>
string(20) "character_set_client"
["Value"]=>
string(7) "utf8mb3"
}
[1]=>
array(2) {
["Variable_name"]=>
string(24) "character_set_connection"
["Value"]=>
string(7) "utf8mb3"
}
[2]=>
array(2) {
["Variable_name"]=>
string(22) "character_set_database"
["Value"]=>
string(7) "utf8mb4"
}
[3]=>
array(2) {
["Variable_name"]=>
string(24) "character_set_filesystem"
["Value"]=>
string(6) "binary"
}
[4]=>
array(2) {
["Variable_name"]=>
string(21) "character_set_results"
["Value"]=>
string(7) "utf8mb3"
}
[5]=>
array(2) {
["Variable_name"]=>
string(20) "character_set_server"
["Value"]=>
string(7) "utf8mb4"
}
[6]=>
array(2) {
["Variable_name"]=>
string(20) "character_set_system"
["Value"]=>
string(7) "utf8mb3"
}
[7]=>
array(2) {
["Variable_name"]=>
string(18) "character_sets_dir"
["Value"]=>
string(26) "/usr/share/mysql/charsets/"
}
}

So the database connection in PHP must be given the character set uft8mb4.

Thanks for the help.

Comment by Karsten Budde [ 2022-01-24 ]

If the character set in PHP is set to utf8md4, then saving the above character will also work.

The ticket can be closed.
Thanks for the help.

with kind regards

Comment by Alexander Barkov [ 2022-01-24 ]

KB_Heinze, thanks for confirmation. Closing.

Generated at Thu Feb 08 09:53:22 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.