Closed jmordica closed 3 years ago
Thanx for pointing this out. It wasn't really a bug it was more a case of me completely forgetting about implementing this 🤣
Wow quick fix! Really appreciate this!
Ok did more testing here and it turns out that it kind of worked but there are a couple of things that still aren't just right:
INT/INTEGER
and has a default value, the default value for the column needs to also be an int. I can see how this didn't get picked up because running SHOW CREATE TABLE dispatcher;
as you can see above shows us that the setid
column (and others that are type int
) have a default value of '0'
. So I can see how this would translate to sqlite as '0'
instead of 0
during the conversion. From my understanding this would need to be converted to an int
vs a string based on my testing.varchar
and has a default value of empty string ''
like the destination
column above, this converts as "destination" VARCHAR(192) NOT NULL
instead of "destination" VARCHAR(192) NOT NULL DEFAULT '',
.So after your latest update, here's the new output of dispatcher:
sqlite> .schema dispatcher
CREATE TABLE "dispatcher" (
"id" INTEGER NOT NULL ,
"setid" INTEGER NOT NULL DEFAULT '0',
"destination" VARCHAR(192) NOT NULL ,
"flags" INTEGER NOT NULL DEFAULT '0',
"priority" INTEGER NOT NULL DEFAULT '0',
"attrs" VARCHAR(128) NOT NULL ,
"description" VARCHAR(64) NOT NULL ,
PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "dispatcher_description" ON "dispatcher" ("description");
When the expected output I believe should be:
sqlite> .schema dispatcher
CREATE TABLE "dispatcher" (
"id" INTEGER NOT NULL ,
"setid" INTEGER NOT NULL DEFAULT 0,
"destination" VARCHAR(192) NOT NULL DEFAULT '',
"flags" INTEGER NOT NULL DEFAULT 0,
"priority" INTEGER NOT NULL DEFAULT 0,
"attrs" VARCHAR(128) NOT NULL DEFAULT '',
"description" VARCHAR(64) NOT NULL DEFAULT '',
PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "dispatcher_description" ON "dispatcher" ("description");
This is partly my fault for not catching this on the original issue 🤦
I see. I thought that numbers have to be wrapped into quotes reading the documentation on the DEFAULT clause. After all, that's what MySQL uses.
Seems I was wrong.
This commit should fix it. Also, check the test test_translate_default_from_mysql_to_sqlite
Ah ok so I just tested number 1 again with the int wrapped in single quotes and it does seem to work. I’m not sure what I was doing before that made it not work. Ans you are right about the docs saying it is acceptable so I would leave that as is and not deviate from the docs.
I see in your latest commit that number 2 should also be resolved. Sorry for the confusion here. I should have done more testing on number 1 before posting.
I made even more explicit tests for this and handled some edge cases, so this should work now as expected. Do check the tests:
Ok this latest change seems to work great. Here's the output:
sqlite> .schema dispatcher
CREATE TABLE "dispatcher" (
"id" INTEGER NOT NULL ,
"setid" INTEGER NOT NULL DEFAULT 0,
"destination" VARCHAR(192) NOT NULL DEFAULT '',
"flags" INTEGER NOT NULL DEFAULT 0,
"priority" INTEGER NOT NULL DEFAULT 0,
"attrs" VARCHAR(128) NOT NULL DEFAULT '',
"description" VARCHAR(64) NOT NULL DEFAULT '',
PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "dispatcher_description" ON "dispatcher" ("description");
I'm a little afraid that if a default int isn't wrapped in ''
people may complain about it not converting back to mysql from sqlite, and since the docs recommend wrapping them should you just leave them wrapped in ''
like they were in your first commit?
I tested it both ways and it works as expected both ways. Sorry to keep re-opening this 😆
Right, so with the latest changes this MySQL DDL
CREATE TABLE `bingo` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`integer_col` int DEFAULT '1',
`integer2_col` int DEFAULT '0',
`varchar_col` varchar(100) COLLATE utf8mb4_general_ci DEFAULT 'lalala',
`varchar2_col` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '1',
`varchar3_col` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '0',
`float_col` float DEFAULT '1234.57',
`bool_col` tinyint(1) DEFAULT '1',
`bool2_col` tinyint(1) DEFAULT '0',
`text_col` text COLLATE utf8mb4_general_ci,
`empty_varchar_col` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
gets converted to this SQLite DDL
CREATE TABLE "bingo" (
"id" INTEGER NOT NULL ,
"integer_col" INTEGER NULL DEFAULT 1,
"integer2_col" INTEGER NULL DEFAULT 0,
"varchar_col" VARCHAR(100) NULL DEFAULT 'lalala',
"varchar2_col" VARCHAR(100) NULL DEFAULT '1',
"varchar3_col" VARCHAR(100) NULL DEFAULT '0',
"float_col" FLOAT NULL DEFAULT '1234.57',
"bool_col" TINYINT NULL DEFAULT 1,
"bool2_col" TINYINT NULL DEFAULT 0,
"text_col" TEXT NULL ,
"empty_varchar_col" VARCHAR(100) NULL DEFAULT '',
PRIMARY KEY ("id")
);
And yes, I'm also concerned about the integers being unwrapped. It's kinda unsafe. I'll put the quotes back.
OK, I've put the quotation wrapping back, so now this MySQL DDL
CREATE TABLE `bingo` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`integer_col` int DEFAULT '1',
`integer2_col` int DEFAULT '0',
`varchar_col` varchar(100) COLLATE utf8mb4_general_ci DEFAULT 'lalala',
`varchar2_col` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '1',
`varchar3_col` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '0',
`float_col` float DEFAULT '1234.57',
`bool_col` tinyint(1) DEFAULT '1',
`bool2_col` tinyint(1) DEFAULT '0',
`text_col` text COLLATE utf8mb4_general_ci,
`empty_varchar_col` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '',
`timestamp_col` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
gets converted to this SQLite DDL
CREATE TABLE "bingo" (
"id" INTEGER NOT NULL ,
"integer_col" INTEGER NULL DEFAULT '1',
"integer2_col" INTEGER NULL DEFAULT '0',
"varchar_col" VARCHAR(100) NULL DEFAULT 'lalala',
"varchar2_col" VARCHAR(100) NULL DEFAULT '1',
"varchar3_col" VARCHAR(100) NULL DEFAULT '0',
"float_col" FLOAT NULL DEFAULT '1234.57',
"bool_col" TINYINT NULL DEFAULT '1',
"bool2_col" TINYINT NULL DEFAULT '0',
"text_col" TEXT NULL ,
"empty_varchar_col" VARCHAR(100) NULL DEFAULT '',
"timestamp_col" DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ("id")
);
Perfection! Sorry for the back and forth here and again, thanks for the promptness.
You're going to hate me. I have tested all column default types and found one more small issue. NULL
defaults.
Here's a mysql table:
CREATE TABLE `address` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`grp` int(11) unsigned NOT NULL DEFAULT '1',
`ip_addr` varchar(50) NOT NULL,
`mask` int(11) NOT NULL DEFAULT '32',
`port` smallint(5) unsigned NOT NULL DEFAULT '0',
`tag` varchar(64) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=latin1
Here's what we get from the conversion tool:
sqlite> .schema address
CREATE TABLE "address" (
"id" INTEGER NOT NULL ,
"grp" INTEGER NOT NULL DEFAULT '1',
"ip_addr" VARCHAR(50) NOT NULL ,
"mask" INTEGER NOT NULL DEFAULT '32',
"port" SMALLINT NOT NULL DEFAULT '0',
"tag" VARCHAR(64) NULL ,
PRIMARY KEY ("id")
);
Notice the tag
column isn't getting the DEFAULT NULL
To be honest I've never even heard of something like DEFAULT NULL
. A column is either NOT NULL
or NULL
. And according to the SQLite docs:
The DEFAULT clause specifies a default value to use for the column if no value is explicitly provided by the user when doing an INSERT. If there is no explicit DEFAULT clause attached to a column definition, then the default value of the column is NULL. An explicit DEFAULT clause may specify that the default value is NULL, a string constant, a blob constant, a signed-number, or any constant expression enclosed in parentheses. A default value may also be one of the special case-independent keywords CURRENT_TIME, CURRENT_DATE or CURRENT_TIMESTAMP. For the purposes of the DEFAULT clause, an expression is considered constant if it contains no sub-queries, column or table references, bound parameters, or string literals enclosed in double-quotes instead of single-quotes.
So the code works as expected and your example up there is perfectly fine.
Ok good deal. I’m new to SQLite. I appreciate it!
FYI MySQL behaves just the same with default null
. As I said, I've never seen it used in either MySQL or SQLite.
Describe the bug The default column values don't seem to get converted to sqlite. Here's the command that was run to generate the output:
Here's the actual table schema in mysql 5.7:
Expected behaviour
Actual result
System Information
BTW, thanks for this tool. It seems to work very well. I've tried others and they all failed to produce a production ready sqlite export but this one seems great :)