@@ -84,6 +84,8 @@ def __init__(self, **kwargs): # noqa: ignore=C901 pylint: disable=R0912
84
84
kwargs .get ("mysql_string_type" ) or "VARCHAR(255)"
85
85
).upper ()
86
86
87
+ self ._with_rowid = kwargs .get ("with_rowid" ) or False
88
+
87
89
sqlite3 .register_adapter (Decimal , adapt_decimal )
88
90
sqlite3 .register_converter ("DECIMAL" , convert_decimal )
89
91
sqlite3 .register_adapter (timedelta , adapt_timedelta )
@@ -196,6 +198,14 @@ def _check_mysql_fulltext_support(version_string):
196
198
return True
197
199
return False
198
200
201
+ def _sqlite_table_has_rowid (self , table ):
202
+ try :
203
+ self ._sqlite_cur .execute ("""SELECT rowid FROM "{}" LIMIT 1""" .format (table ))
204
+ self ._sqlite_cur .fetchall ()
205
+ return True
206
+ except sqlite3 .OperationalError :
207
+ return False
208
+
199
209
def _create_database (self ):
200
210
try :
201
211
self ._mysql_cur .execute (
@@ -266,11 +276,15 @@ def _column_type_length(cls, column_type, default=None):
266
276
return "({})" .format (default )
267
277
return ""
268
278
269
- def _create_table (self , table_name ):
279
+ def _create_table (self , table_name , transfer_rowid = False ):
270
280
primary_key = ""
281
+ primary_key_length = ""
271
282
272
283
sql = "CREATE TABLE IF NOT EXISTS `{}` ( " .format (table_name )
273
284
285
+ if transfer_rowid :
286
+ sql += " `rowid` BIGINT NOT NULL, "
287
+
274
288
self ._sqlite_cur .execute ('PRAGMA table_info("{}")' .format (table_name ))
275
289
276
290
for row in self ._sqlite_cur .fetchall ():
@@ -287,10 +301,20 @@ def _create_table(self, table_name):
287
301
)
288
302
if column ["pk" ]:
289
303
primary_key = column ["name" ]
304
+ # In case we have a non-numeric primary key
305
+ column_type = self ._translate_type_from_sqlite_to_mysql (column ["type" ])
306
+ if column_type in {"TEXT" , "BLOB" } or column_type .startswith (
307
+ ("CHAR" , "VARCHAR" )
308
+ ):
309
+ primary_key_length = self ._column_type_length (column_type , 255 )
290
310
291
311
sql = sql .rstrip (", " )
292
312
if primary_key :
293
- sql += ", PRIMARY KEY (`{}`)" .format (primary_key )
313
+ sql += ", PRIMARY KEY (`{column}`{length})" .format (
314
+ column = primary_key , length = primary_key_length ,
315
+ )
316
+ if transfer_rowid :
317
+ sql += ", CONSTRAINT `{}_rowid` UNIQUE (`rowid`)" .format (table_name )
294
318
sql += " ) ENGINE = InnoDB CHARACTER SET utf8mb4"
295
319
296
320
try :
@@ -343,6 +367,7 @@ def _add_indices(self, table_name): # noqa: ignore=C901 pylint: disable=R0914
343
367
column_list = []
344
368
for index_info in index_infos :
345
369
index_length = ""
370
+ # Limit the max BLOB field index length to 255
346
371
if table_columns [index_info ["name" ]].upper () == "BLOB" :
347
372
index_length = "({})" .format (255 )
348
373
else :
@@ -364,7 +389,7 @@ def _add_indices(self, table_name): # noqa: ignore=C901 pylint: disable=R0914
364
389
""" .format (
365
390
table = table_name ,
366
391
index_type = index_type ,
367
- name = index ["name" ],
392
+ name = index ["name" ][: 64 ], # Limit the index name to 64 chars.
368
393
columns = index_columns ,
369
394
)
370
395
@@ -472,8 +497,13 @@ def transfer(self):
472
497
for row in self ._sqlite_cur .fetchall ():
473
498
table = dict (row )
474
499
500
+ # check if we're transferring rowid
501
+ transfer_rowid = self ._with_rowid and self ._sqlite_table_has_rowid (
502
+ table ["name" ]
503
+ )
504
+
475
505
# create the table
476
- self ._create_table (table ["name" ])
506
+ self ._create_table (table ["name" ], transfer_rowid = transfer_rowid )
477
507
478
508
# get the size of the data
479
509
self ._sqlite_cur .execute (
@@ -485,7 +515,14 @@ def transfer(self):
485
515
if total_records > 0 :
486
516
# populate it
487
517
self ._logger .info ("Transferring table %s" , table ["name" ])
488
- self ._sqlite_cur .execute ('SELECT * FROM "{}"' .format (table ["name" ]))
518
+ self ._sqlite_cur .execute (
519
+ """
520
+ SELECT {rowid} * FROM "{table_name}"
521
+ """ .format (
522
+ rowid = 'rowid as "rowid",' if transfer_rowid else "" ,
523
+ table_name = table ["name" ],
524
+ )
525
+ )
489
526
columns = [column [0 ] for column in self ._sqlite_cur .description ]
490
527
sql = "INSERT IGNORE INTO `{table}` ({fields}) VALUES ({placeholders})" .format ( # noqa: ignore=E501 pylint: disable=C0301
491
528
table = table ["name" ],
0 commit comments