Opened 6 years ago
Closed 6 years ago
#13128 closed defect (fixed)
Timeline broken with a MySQL 8.0 backend
Reported by: | anonymous | Owned by: | Jun Omae |
---|---|---|---|
Priority: | normal | Milestone: | 1.0.18 |
Component: | database backend | Version: | 1.2.2 |
Severity: | major | Keywords: | mysql |
Cc: | Branch: | log:jomae.git@t13128+1.0-stable log:jomae.git@t13128+1.2-stable log:jomae.git@t13128+trunk | |
Release Notes: |
Compatibility fix with MySQL 8.0. |
||
API Changes: | |||
Internal Changes: |
Description (last modified by )
After upgrading from MySQL 5.7 to MySQL 8.0, I'm getting the following error message when accessing the "Timeline" in my Trac instance:
Trac detected an internal error: ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'system WHERE name='initial_database_version'' at line 1") Python Traceback Most recent call last: File "C:/server/trac/.egg-cache/trac-1.2.2-py2.7-win32.egg-tmp/trac/timeline/templates/timeline.html", line 63, in <Expression u"event.render('description', context)"> ${event.render('description', context)} File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/timeline/web_ui.py", line 374, in <lambda> provider.render_timeline_event(context, field, event) File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/ticket/web_ui.py", line 411, in render_timeline_event t_context.set_hints(preserve_newlines=self.must_preserve_newlines) File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/util/__init__.py", line 1202, in __get__ result = self.fn(instance) File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/ticket/web_ui.py", line 125, in must_preserve_newlines preserve_newlines = self.env.database_initial_version >= 21 # 0.11 File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/util/__init__.py", line 1202, in __get__ result = self.fn(instance) File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/env.py", line 613, in database_initial_version .get_database_version('initial_database_version') File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/db/api.py", line 480, in get_database_version """, (name,)) File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/db/api.py", line 122, in execute return db.execute(query, params) File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/db/util.py", line 128, in execute cursor.execute(query, params if params is not None else []) File "c:/users/trac/appdata/local/temp/easy_install-ni58x7/Trac-1.2.2-py2.7-win32.egg.tmp/trac/db/util.py", line 72, in execute return self.cursor.execute(sql_escape_percent(sql), args) File "C:/server/Python27/lib/site-packages/MySQLdb/cursors.py", line 205, in execute self.errorhandler(self, exc, value) File "C:/server/Python27/lib/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler raise errorclass, errorvalue
Reason: system
has become a reserved keyword in MySQL 8.0.
Location: tags/trac-1.2.3/trac/db/api.py#L479
Attachments (2)
Change History (20)
by , 6 years ago
Attachment: | Trac - MySQL 8.0 - Timeline.png added |
---|
comment:1 by , 6 years ago
I have added a patch that fixed the problem for me (I checked out the 1.2-branch, applied the changes and python ./setup.py install
ed it).
comment:2 by , 6 years ago
Keywords: | mysql added |
---|---|
Milestone: | 1.2.4 → 1.0.18 |
Owner: | set to |
Status: | new → assigned |
Version: | → 1.2.3 |
Thanks for the reporting and patch, however your patch doesn't work with PostgreSQL.
I'll fix it based the patch.
comment:3 by , 6 years ago
Version: | 1.2.3 → 1.2.2 |
---|
comment:4 by , 6 years ago
Description: | modified (diff) |
---|
comment:5 by , 6 years ago
Branch: | → log:jomae.git@t13128+1.0-stable log:jomae.git@t13128+1.2-stable log:jomae.git@t13128+trunk |
---|
I noticed another issue on unit tests.
In reset_mysql_db
, use DELETE FROM
or TRUNCATE TABLE
based on auto_increment
column of information_schema.tables
. However, with MySQL 8.0, the auto_increment
is 1
even if the next value is not 1
.
Resetting database doesn't work due to the behavior and unit tests fail.
mysql> SELECT table_schema, table_name, auto_increment FROM information_schema.tables WHERE table_name='ticket'; +--------------+------------+----------------+ | TABLE_SCHEMA | TABLE_NAME | AUTO_INCREMENT | +--------------+------------+----------------+ | tractest | ticket | 1 | +--------------+------------+----------------+ 1 row in set (0.01 sec) mysql> SHOW CREATE TABLE ticket\G *************************** 1. row *************************** Table: ticket Create Table: CREATE TABLE `ticket` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `type` text COLLATE utf8mb4_bin, `time` bigint(20) DEFAULT NULL, `changetime` bigint(20) DEFAULT NULL, `component` text COLLATE utf8mb4_bin, `severity` text COLLATE utf8mb4_bin, `priority` text COLLATE utf8mb4_bin, `owner` text COLLATE utf8mb4_bin, `reporter` text COLLATE utf8mb4_bin, `cc` text COLLATE utf8mb4_bin, `version` text COLLATE utf8mb4_bin, `milestone` text COLLATE utf8mb4_bin, `status` text COLLATE utf8mb4_bin, `resolution` text COLLATE utf8mb4_bin, `summary` text COLLATE utf8mb4_bin, `description` text COLLATE utf8mb4_bin, `keywords` text COLLATE utf8mb4_bin, PRIMARY KEY (`id`), KEY `ticket_time_idx` (`time`), KEY `ticket_status_idx` (`status`(191)) ) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin 1 row in set (0.01 sec)
Instead, we could use extra
column of information_schema.columns
to detect whether auto_increment
column is used in the table.
mysql> SELECT table_schema, table_name, column_name, extra -> FROM information_schema.columns -> WHERE extra='auto_increment' -> AND table_schema='tractest' -> ORDER BY 1, 2, 3; +--------------+------------+-------------+----------------+ | TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME | EXTRA | +--------------+------------+-------------+----------------+ | tractest | report | id | auto_increment | | tractest | ticket | id | auto_increment | +--------------+------------+-------------+----------------+ 2 rows in set (0.00 sec)
Proposed changes:
comment:7 by , 6 years ago
follow-up: 9 comment:8 by , 6 years ago
List of plugins on trac-hacks using system table:
$ git grep -i '\<\(FROM\|INSERT\s*INTO\|UPDATE\)\s\+system\>' -- '*.py' | sed -e '\!/tests/!d; s#/.*$##' | sort | uniq -c 8 announcerplugin 4 backlogplugin 4 bittenforgitplugin 3 bookmarkplugin 3 boxdbplugin 4 calendarplugin 4 cardsplugin 12 clientsplugin 6 codereviewerplugin 2 componenthierarchyplugin 3 contactsplugin 12 directoryauthplugin 21 discussionplugin 20 downloadsplugin 9 estimatorplugin 2 exowebcodereviewplugin 4 extendedversionplugin 6 fullblogplugin 4 fulltextsearchplugin 2 geoticketplugin 9 gringottsplugin 4 guestbookplugin 6 hidevalsplugin 3 jobcontrolplugin 3 mailarchiveplugin 12 masterticketsplugin 8 mathcaptchaplugin 3 milestoneteamsplugin 2 mindmapmacro 3 multiprojectbacklogplugin 9 narcissusplugin 97 peerreviewplugin 2 perforceplugin 3 remoteticketplugin 24 screenshotsplugin 3 serverdownmacro 45 simplemultiprojectplugin 24 tagsplugin 3 teamcalendarplugin 4 timetrackingplugin 36 timingandestimationplugin 3 tracblplugin 15 tracforgeplugin 48 tracformsplugin 6 trachacksplugin 9 trachoursplugin 6 tracjsganttplugin 4 tracmilemixviewplugin 8 tracpasteplugin 4 tracreleaseplugin 8 tracreportmanagerplugin 5 tracsecdlplugin 4 tracticketchainedfieldsplugin 4 tracticketchangesetsplugin 12 tractickettemplateplugin 4 tractweakuiplugin 8 tracunreadplugin 4 visitcountermacro 29 voteplugin 16 watchlistplugin 4 weekplanplugin 6 wikiformsplugin 9 worklogplugin
comment:9 by , 6 years ago
Replying to Jun Omae:
List of plugins on trac-hacks using system table:
Eventually, plugins should be modified to use DatabaseManager.{set_database_version/get_database_version}
(added in Trac 1.2). Some of those listed have already been modified in their latest release (e.g. CardsPlugin in r16098).
comment:10 by , 6 years ago
Yeah, the following plugins already use DatabaseManager.[gs]et_database_version
methods.
$ git grep -w '[gs]et_database_version' -- '*.py' | sed -e 's#^\([^/]*/[^/]*\).*#\1#' | sort | uniq -c 9 bookmarkplugin/trunk 3 cardsplugin/trunk 17 codereviewerplugin/1.0 1 componenthierarchyplugin/1.2 1 contactsplugin/1.2 1 hidevalsplugin/1.2 3 mailarchiveplugin/trunk 12 masterticketsplugin/tags 12 masterticketsplugin/trunk 2 mathcaptchaplugin/1.2 2 mindmapmacro/1.2 3 onsitenotificationsplugin/trunk 3 packagerepositoryplugin/trunk 1 privatereportsplugin/trunk 3 pullrequestsplugin/trunk 6 screenshotsplugin/1.2 18 simplemultiprojectplugin/trunk 11 teamcalendarplugin/1.0 3 timetrackingplugin/trunk 8 tracpasteplugin/trunk 1 tracticketchainedfieldsplugin/1.2 1 tracticketchangelogplugin/1.2 1 tractweakuiplugin/1.2 13 voteplugin/trunk 3 weekplanplugin/trunk
follow-up: 12 comment:11 by , 6 years ago
Given that information, maybe defer the table rename to 1.5.x, or later?
comment:12 by , 6 years ago
Replying to Ryan J Ollos:
Given that information, maybe defer the table rename to 1.5.x, or later?
Yes, why not.
All those plugins using directly system
would need to be adapted as well if they were to support MySQL 8. And to that end, doing a system
→ trac_system
substitution is then much easier for them than adding the db.quote()
.
follow-ups: 15 16 comment:13 by , 6 years ago
I don't think the renaming is good idea.
The renaming would be performed by upgrade/dbN.py. The database version would be to retrieve from system
or trac_system
table. However, the database version is needed to determine whether system
or trac_system
table. That is cyclic.
comment:14 by , 6 years ago
More consideration of table rename: to support Trac < 1.2 with MySQL 8.0, plugins will need to db.quote
the system
table. There's no way around that since we wouldn't add a DB upgrade step in a minor release, and even if we did the problem would exist for plugins supporting Trac < 1.0.18.
For Trac ≥ 1.2, plugins can use the DatabaseManager
API and avoid direct interactions with the system
table, thereby eliminating any concern over db.quote
vs system
rename. Given that we'd only rename the table on trunk, it probably makes more sense just to push all plugins supporting Trac > 1.2 to use the DatabaseManager
API, rather than db.quote
or system
→ trac_system
.
Keeping in mind that even using the DatabaseManager
API with Trac < 1.2.4, the plugin won't be compatible with MySQL 8.0. The easy solution there is to tell the user to upgrade their Trac instance; it's not the plugin's problem.
Or plugins can just stop supporting Trac < 1.2, which is definitely my preference ;)
comment:15 by , 6 years ago
Replying to Jun Omae:
I don't think the renaming is good idea.
The renaming would be performed by upgrade/dbN.py. The database version would be to retrieve from
system
ortrac_system
table. However, the database version is needed to determine whethersystem
ortrac_system
table. That is cyclic.
This is a good point. It seems this could lead to many problems. (Even without plugins.) Also to support upgrading from an old environment, a new Trac would have to support system
indefinitely anyway to know which upgrades to apply.
comment:16 by , 6 years ago
Replying to Jun Omae:
The renaming would be performed by upgrade/dbN.py. The database version would be to retrieve from
system
ortrac_system
table. However, the database version is needed to determine whethersystem
ortrac_system
table. That is cyclic.
Another idea, we could create system
view to trac_system
table after the renaming, to determine the database version. However, insert/update statements should be executed to trac_system
table because a view in SQLite is not writable (writable in PostgreSQL and MySQL).
comment:17 by , 6 years ago
Release Notes: | modified (diff) |
---|
The changes using db.quote()
have been committed in [16881-16883].
comment:18 by , 6 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
I'm going to close this one under assumption we can make another issue if more work is to be done after 1.0.18.
ou have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'system WHERE name='initial_database_version at line 1