Description:
CHARACTER_MAXIMUM_LENGTH and CHARACTER_OCTET_LENGTH for LONGTEXT data_type reported in information_schema.routines and information_schema.parameters (with Latin1 character set) reports as
DATA_TYPE: longtext
CHARACTER_MAXIMUM_LENGTH: 2147483647
CHARACTER_OCTET_LENGTH: 2147483647
Both the routines and parameters tables define CHARACTER_MAXIMUM_LENGTH and CHARACTER_OCTET_LENGTH as int(21) in contrast to information_schema.columns
which defines these columns as bigint(21) unsigned.
LONGTEXT should be 4294967295 for latin1 charset so the value returned by these tables is truncated to half the expected size.
This appears to be a possible cause of an error I get when when querying information_schema.routines with strict_mode enabled which returns
mysql> select tap.has_function('tap','has_function','');
ERROR 1264 (22003): Out of range value for column 'CHARACTER_MAXIMUM_LENGTH' at row 1
mysql> select tap.has_function('tap','has_function','');
+------------------------------------------------+
| tap.has_function('tap','has_function','') |
+------------------------------------------------+
| ok 58 - Function tap.has_function should exist |
+------------------------------------------------+
1 row in set (0.06 sec)
How to repeat:
mysql> show create table information_schema.routines\G
*************************** 1. row ***************************
Table: ROUTINES
Create Table: CREATE TEMPORARY TABLE `ROUTINES` (
`SPECIFIC_NAME` varchar(64) NOT NULL DEFAULT '',
`ROUTINE_CATALOG` varchar(512) NOT NULL DEFAULT '',
`ROUTINE_SCHEMA` varchar(64) NOT NULL DEFAULT '',
`ROUTINE_NAME` varchar(64) NOT NULL DEFAULT '',
`ROUTINE_TYPE` varchar(9) NOT NULL DEFAULT '',
`DATA_TYPE` varchar(64) NOT NULL DEFAULT '',
`CHARACTER_MAXIMUM_LENGTH` int(21) DEFAULT NULL,
`CHARACTER_OCTET_LENGTH` int(21) DEFAULT NULL,
`NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
`NUMERIC_SCALE` int(21) DEFAULT NULL,
`DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
`CHARACTER_SET_NAME` varchar(64) DEFAULT NULL,
`COLLATION_NAME` varchar(64) DEFAULT NULL,
`DTD_IDENTIFIER` longtext,
`ROUTINE_BODY` varchar(8) NOT NULL DEFAULT '',
`ROUTINE_DEFINITION` longtext,
`EXTERNAL_NAME` varchar(64) DEFAULT NULL,
`EXTERNAL_LANGUAGE` varchar(64) DEFAULT NULL,
`PARAMETER_STYLE` varchar(8) NOT NULL DEFAULT '',
`IS_DETERMINISTIC` varchar(3) NOT NULL DEFAULT '',
`SQL_DATA_ACCESS` varchar(64) NOT NULL DEFAULT '',
`SQL_PATH` varchar(64) DEFAULT NULL,
`SECURITY_TYPE` varchar(7) NOT NULL DEFAULT '',
`CREATED` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`LAST_ALTERED` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`SQL_MODE` varchar(8192) NOT NULL DEFAULT '',
`ROUTINE_COMMENT` longtext NOT NULL,
`DEFINER` varchar(93) NOT NULL DEFAULT '',
`CHARACTER_SET_CLIENT` varchar(32) NOT NULL DEFAULT '',
`COLLATION_CONNECTION` varchar(32) NOT NULL DEFAULT '',
`DATABASE_COLLATION` varchar(32) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> show create table information_schema.parameters\G
*************************** 1. row ***************************
Table: PARAMETERS
Create Table: CREATE TEMPORARY TABLE `PARAMETERS` (
`SPECIFIC_CATALOG` varchar(512) NOT NULL DEFAULT '',
`SPECIFIC_SCHEMA` varchar(64) NOT NULL DEFAULT '',
`SPECIFIC_NAME` varchar(64) NOT NULL DEFAULT '',
`ORDINAL_POSITION` int(21) NOT NULL DEFAULT '0',
`PARAMETER_MODE` varchar(5) DEFAULT NULL,
`PARAMETER_NAME` varchar(64) DEFAULT NULL,
`DATA_TYPE` varchar(64) NOT NULL DEFAULT '',
`CHARACTER_MAXIMUM_LENGTH` int(21) DEFAULT NULL,
`CHARACTER_OCTET_LENGTH` int(21) DEFAULT NULL,
`NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
`NUMERIC_SCALE` int(21) DEFAULT NULL,
`DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
`CHARACTER_SET_NAME` varchar(64) DEFAULT NULL,
`COLLATION_NAME` varchar(64) DEFAULT NULL,
`DTD_IDENTIFIER` longtext NOT NULL,
`ROUTINE_TYPE` varchar(9) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> show create table information_schema.columns\G
*************************** 1. row ***************************
Table: COLUMNS
Create Table: CREATE TEMPORARY TABLE `COLUMNS` (
`TABLE_CATALOG` varchar(512) NOT NULL DEFAULT '',
`TABLE_SCHEMA` varchar(64) NOT NULL DEFAULT '',
`TABLE_NAME` varchar(64) NOT NULL DEFAULT '',
`COLUMN_NAME` varchar(64) NOT NULL DEFAULT '',
`ORDINAL_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0',
`COLUMN_DEFAULT` longtext,
`IS_NULLABLE` varchar(3) NOT NULL DEFAULT '',
`DATA_TYPE` varchar(64) NOT NULL DEFAULT '',
`CHARACTER_MAXIMUM_LENGTH` bigint(21) unsigned DEFAULT NULL,
`CHARACTER_OCTET_LENGTH` bigint(21) unsigned DEFAULT NULL,
`NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
`NUMERIC_SCALE` bigint(21) unsigned DEFAULT NULL,
`DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
`CHARACTER_SET_NAME` varchar(32) DEFAULT NULL,
`COLLATION_NAME` varchar(32) DEFAULT NULL,
`COLUMN_TYPE` longtext NOT NULL,
`COLUMN_KEY` varchar(3) NOT NULL DEFAULT '',
`EXTRA` varchar(30) NOT NULL DEFAULT '',
`PRIVILEGES` varchar(80) NOT NULL DEFAULT '',
`COLUMN_COMMENT` varchar(1024) NOT NULL DEFAULT '',
`GENERATION_EXPRESSION` longtext NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> delimiter //
mysql> create function foo() returns LONGTEXT begin declare bar LONGTEXT; set bar = 'a'; return bar; end //
mysql> delimiter ;
mysql> select * from information_schema.routines where routine_name = 'foo'\G
*************************** 1. row ***************************
SPECIFIC_NAME: foo
ROUTINE_CATALOG: def
ROUTINE_SCHEMA: tap
ROUTINE_NAME: foo
ROUTINE_TYPE: FUNCTION
DATA_TYPE: longtext
CHARACTER_MAXIMUM_LENGTH: 2147483647
CHARACTER_OCTET_LENGTH: 2147483647
NUMERIC_PRECISION: NULL
NUMERIC_SCALE: NULL
DATETIME_PRECISION: NULL
CHARACTER_SET_NAME: latin1
COLLATION_NAME: latin1_swedish_ci
DTD_IDENTIFIER: longtext
ROUTINE_BODY: SQL
ROUTINE_DEFINITION: begin declare bar LONGTEXT; set bar = 'a'; return bar; end
EXTERNAL_NAME: NULL
EXTERNAL_LANGUAGE: NULL
PARAMETER_STYLE: SQL
IS_DETERMINISTIC: NO
SQL_DATA_ACCESS: CONTAINS SQL
SQL_PATH: NULL
SECURITY_TYPE: DEFINER
CREATED: 2017-11-07 08:46:48
LAST_ALTERED: 2017-11-07 08:46:48
SQL_MODE: STRICT_ALL_TABLES
ROUTINE_COMMENT:
DEFINER: root@localhost
CHARACTER_SET_CLIENT: latin1
COLLATION_CONNECTION: latin1_swedish_ci
DATABASE_COLLATION: latin1_swedish_ci
1 row in set (0.02 sec)
mysql> select * from information_schema.parameters where specific_name = 'foo'\G
*************************** 1. row ***************************
SPECIFIC_CATALOG: def
SPECIFIC_SCHEMA: tap
SPECIFIC_NAME: foo
ORDINAL_POSITION: 0
PARAMETER_MODE: NULL
PARAMETER_NAME: NULL
DATA_TYPE: longtext
CHARACTER_MAXIMUM_LENGTH: 2147483647
CHARACTER_OCTET_LENGTH: 2147483647
NUMERIC_PRECISION: NULL
NUMERIC_SCALE: NULL
DATETIME_PRECISION: NULL
CHARACTER_SET_NAME: latin1
COLLATION_NAME: latin1_swedish_ci
DTD_IDENTIFIER: longtext
ROUTINE_TYPE: FUNCTION
1 row in set (0.02 sec)
compare with
mysql> create table foo(a LONGTEXT);
Query OK, 0 rows affected (0.44 sec)
mysql> select * from information_schema.columns where table_name = 'foo'\G
*************************** 1. row ***************************
TABLE_CATALOG: def
TABLE_SCHEMA: tap
TABLE_NAME: foo
COLUMN_NAME: a
ORDINAL_POSITION: 1
COLUMN_DEFAULT: NULL
IS_NULLABLE: YES
DATA_TYPE: longtext
CHARACTER_MAXIMUM_LENGTH: 4294967295
CHARACTER_OCTET_LENGTH: 4294967295
NUMERIC_PRECISION: NULL
NUMERIC_SCALE: NULL
DATETIME_PRECISION: NULL
CHARACTER_SET_NAME: latin1
COLLATION_NAME: latin1_swedish_ci
COLUMN_TYPE: longtext
COLUMN_KEY:
EXTRA:
PRIVILEGES: select,insert,update,references
COLUMN_COMMENT:
GENERATION_EXPRESSION:
1 row in set (0.04 sec)
Suggested fix:
Change definition of CHARACTER_MAXIMUM_LENGTH and CHARACTER_OCTET_LENGTH in information_schema.routines and information_schema.parameters to match the definition for information_schema.columns.