Skip to content

Commit

Permalink
ibd2sql v1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ddcw committed Jan 9, 2024
1 parent b40925b commit 9cbb218
Show file tree
Hide file tree
Showing 15 changed files with 2,938 additions and 396 deletions.
654 changes: 429 additions & 225 deletions README.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions ibd2sql/COLLATIONS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# select * from information_schema.COLLATIONS
# select concat("{",group_concat(concat(id,":('",CHARACTER_SET_NAME, "','", COLLATION_NAME, "')")),"}") from information_schema.COLLATIONS;

COLLID_TO_CHAR = {32:('armscii8','armscii8_general_ci'),64:('armscii8','armscii8_bin'),11:('ascii','ascii_general_ci'),65:('ascii','ascii_bin'),1:('big5','big5_chinese_ci'),84:('big5','big5_bin'),63:('binary','binary'),26:('cp1250','cp1250_general_ci'),34:('cp1250','cp1250_czech_cs'),44:('cp1250','cp1250_croatian_ci'),66:('cp1250','cp1250_bin'),99:('cp1250','cp1250_polish_ci'),14:('cp1251','cp1251_bulgarian_ci'),23:('cp1251','cp1251_ukrainian_ci'),50:('cp1251','cp1251_bin'),51:('cp1251','cp1251_general_ci'),52:('cp1251','cp1251_general_cs'),57:('cp1256','cp1256_general_ci'),67:('cp1256','cp1256_bin'),29:('cp1257','cp1257_lithuanian_ci'),58:('cp1257','cp1257_bin'),59:('cp1257','cp1257_general_ci'),4:('cp850','cp850_general_ci'),80:('cp850','cp850_bin'),40:('cp852','cp852_general_ci'),81:('cp852','cp852_bin'),36:('cp866','cp866_general_ci'),68:('cp866','cp866_bin'),95:('cp932','cp932_japanese_ci'),96:('cp932','cp932_bin'),3:('dec8','dec8_swedish_ci'),69:('dec8','dec8_bin'),97:('eucjpms','eucjpms_japanese_ci'),98:('eucjpms','eucjpms_bin'),19:('euckr','euckr_korean_ci'),85:('euckr','euckr_bin'),248:('gb18030','gb18030_chinese_ci'),249:('gb18030','gb18030_bin'),250:('gb18030','gb18030_unicode_520_ci'),24:('gb2312','gb2312_chinese_ci'),86:('gb2312','gb2312_bin'),28:('gbk','gbk_chinese_ci'),87:('gbk','gbk_bin'),92:('geostd8','geostd8_general_ci'),93:('geostd8','geostd8_bin'),25:('greek','greek_general_ci'),70:('greek','greek_bin'),16:('hebrew','hebrew_general_ci'),71:('hebrew','hebrew_bin'),6:('hp8','hp8_english_ci'),72:('hp8','hp8_bin'),37:('keybcs2','keybcs2_general_ci'),73:('keybcs2','keybcs2_bin'),7:('koi8r','koi8r_general_ci'),74:('koi8r','koi8r_bin'),22:('koi8u','koi8u_general_ci'),75:('koi8u','koi8u_bin'),5:('latin1','latin1_german1_ci'),8:('latin1','latin1_swedish_ci'),15:('latin1','latin1_danish_ci'),31:('latin1','latin1_german2_ci'),47:('latin1','latin1_bin'),48:('latin1','latin1_general_ci'),49:('latin1','latin1_general_cs'),94:('latin1','latin1_spanish_ci'),2:('latin2','latin2_czech_cs'),9:('latin2','latin2_general_ci'),21:('latin2','latin2_hungarian_ci'),27:('latin2','latin2_croatian_ci'),77:('latin2','latin2_bin'),30:('latin5','latin5_turkish_ci'),78:('latin5','latin5_bin'),20:('latin7','latin7_estonian_cs'),41:('latin7','latin7_general_ci'),42:('latin7','latin7_general_cs'),79:('latin7','latin7_bin'),38:('macce','macce_general_ci'),43:('macce','macce_bin'),39:('macroman','macroman_general_ci'),53:('macroman','macroman_bin'),13:('sjis','sjis_japanese_ci'),88:('sjis','sjis_bin'),10:('swe7','swe7_swedish_ci'),82:('swe7','swe7_bin'),18:('tis620','tis620_thai_ci'),89:('tis620','tis620_bin'),35:('ucs2','ucs2_general_ci'),90:('ucs2','ucs2_bin'),128:('ucs2','ucs2_unicode_ci'),129:('ucs2','ucs2_icelandic_ci'),130:('ucs2','ucs2_latvian_ci'),131:('ucs2','ucs2_romanian_ci'),132:('ucs2','ucs2_slovenian_ci'),133:('ucs2','ucs2_polish_ci'),134:('ucs2','ucs2_estonian_ci'),135:('ucs2','ucs2_spanish_ci'),136:('ucs2','ucs2_swedish_ci'),137:('ucs2','ucs2_turkish_ci'),138:('ucs2','ucs2_czech_ci'),139:('ucs2','ucs2_danish_ci'),140:('ucs2','ucs2_lithuanian_ci'),141:('ucs2','ucs2_slovak_ci'),142:('ucs2','ucs2_spanish2_ci'),143:('ucs2','ucs2_roman_ci'),144:('ucs2','ucs2_persian_ci'),145:('ucs2','ucs2_esperanto_ci'),146:('ucs2','ucs2_hungarian_ci'),147:('ucs2','ucs2_sinhala_ci'),148:('ucs2','ucs2_german2_ci'),149:('ucs2','ucs2_croatian_ci'),150:('ucs2','ucs2_unicode_520_ci'),151:('ucs2','ucs2_vietnamese_ci'),159:('ucs2','ucs2_general_mysql500_ci'),12:('ujis','ujis_japanese_ci'),91:('ujis','ujis_bin'),54:('utf16','utf16_general_ci'),55:('utf16','utf16_bin'),101:('utf16','utf16_unicode_ci'),102:('utf16','utf16_icelandic_ci'),103:('utf16','utf16_latvian_ci'),104:('utf16','utf16_romanian_ci'),105:('utf16','utf16_slovenian_ci'),106:('utf16','utf16_polish_ci'),107:('utf16','utf16_estonian_ci'),108:('utf16','utf16_spanish_ci'),109:('utf16','utf16_swedish_ci'),110:('utf16','utf16_turkish_ci'),111:('utf16','utf16_czech_ci'),112:('utf16','utf16_danish_ci'),113:('utf16','utf16_lithuanian_ci'),114:('utf16','utf16_slovak_ci'),115:('utf16','utf16_spanish2_ci'),116:('utf16','utf16_roman_ci'),117:('utf16','utf16_persian_ci'),118:('utf16','utf16_esperanto_ci'),119:('utf16','utf16_hungarian_ci'),120:('utf16','utf16_sinhala_ci'),121:('utf16','utf16_german2_ci'),122:('utf16','utf16_croatian_ci'),123:('utf16','utf16_unicode_520_ci'),124:('utf16','utf16_vietnamese_ci'),56:('utf16le','utf16le_general_ci'),62:('utf16le','utf16le_bin'),60:('utf32','utf32_general_ci'),61:('utf32','utf32_bin'),160:('utf32','utf32_unicode_ci'),161:('utf32','utf32_icelandic_ci'),162:('utf32','utf32_latvian_ci'),163:('utf32','utf32_romanian_ci'),164:('utf32','utf32_slovenian_ci'),165:('utf32','utf32_polish_ci'),166:('utf32','utf32_estonian_ci'),167:('utf32','utf32_spanish_ci'),168:('utf32','utf32_swedish_ci'),169:('utf32','utf32_turkish_ci'),170:('utf32','utf32_czech_ci'),171:('utf32','utf32_danish_ci'),172:('utf32','utf32_lithuanian_ci'),173:('utf32','utf32_slovak_ci'),174:('utf32','utf32_spanish2_ci'),175:('utf32','utf32_roman_ci'),176:('utf32','utf32_persian_ci'),177:('utf32','utf32_esperanto_ci'),178:('utf32','utf32_hungarian_ci'),179:('utf32','utf32_sinhala_ci'),180:('utf32','utf32_german2_ci'),181:('utf32','utf32_croatian_ci'),182:('utf32','utf32_unicode_520_ci'),183:('utf32','utf32_vietnamese_ci'),33:('utf8','utf8_general_ci'),76:('utf8','utf8_tolower_ci'),83:('utf8','utf8_bin'),192:('utf8','utf8_unicode_ci'),193:('utf8','utf8_icelandic_ci'),194:('utf8','utf8_latvian_ci'),195:('utf8','utf8_romanian_ci'),196:('utf8','utf8_slovenian_ci'),197:('utf8','utf8_polish_ci'),198:('utf8','utf8_estonian_ci'),199:('utf8','utf8_spanish_ci'),200:('utf8','utf8_swedish_ci'),201:('utf8','utf8_turkish_ci'),202:('utf8','utf8_czech_ci'),203:('utf8','utf8_danish_ci'),204:('utf8','utf8_lithuanian_ci'),205:('utf8','utf8_slovak_ci'),206:('utf8','utf8_spanish2_ci'),207:('utf8','utf8_roman_ci'),208:('utf8','utf8_persian_ci'),209:('utf8','utf8_esperanto_ci'),210:('utf8','utf8_hungarian_ci'),211:('utf8','utf8_sinhala_ci'),212:('utf8','utf8_german2_ci'),213:('utf8','utf8_croatian_ci'),214:('utf8','utf8_unicode_520_ci'),215:('utf8','utf8_vietnamese_ci'),223:('utf8','utf8_general_mysql500_ci'),45:('utf8mb4','utf8mb4_general_ci'),46:('utf8mb4','utf8mb4_bin'),224:('utf8mb4','utf8mb4_unicode_ci'),225:('utf8mb4','utf8mb4_icelandic_ci'),226:('utf8mb4','utf8mb4_latvian_ci'),227:('utf8mb4','utf8mb4_romanian_ci'),228:('utf8mb4','utf8mb4_slovenian_ci'),229:('utf8mb4','utf8mb4_polish_ci'),230:('utf8mb4','utf8mb4_estonian_ci'),231:('utf8mb4','utf8mb4_spanish_ci'),232:('utf8mb4','utf8mb4_swedish_ci'),233:('utf8mb4','utf8mb4_turkish_ci'),234:('utf8mb4','utf8mb4_czech_ci'),235:('utf8mb4','utf8mb4_danish_ci'),236:('utf8mb4','utf8mb4_lithuanian_ci'),237:('utf8mb4','utf8mb4_slovak_ci'),238:('utf8mb4','utf8mb4_spanish2_ci'),239:('utf8mb4','utf8mb4_roman_ci'),240:('utf8mb4','utf8mb4_persian_ci'),241:('utf8mb4','utf8mb4_esperanto_ci'),242:('utf8mb4','utf8mb4_hungarian_ci'),243:('utf8mb4','utf8mb4_sinhala_ci'),244:('utf8mb4','utf8mb4_german2_ci'),245:('utf8mb4','utf8mb4_croatian_ci'),246:('utf8mb4','utf8mb4_unicode_520_ci'),247:('utf8mb4','utf8mb4_vietnamese_ci'),255:('utf8mb4','utf8mb4_0900_ai_ci'),256:('utf8mb4','utf8mb4_de_pb_0900_ai_ci'),257:('utf8mb4','utf8mb4_is_0900_ai_ci'),258:('utf8mb4','utf8mb4_lv_0900_ai_ci'),259:('utf8mb4','utf8mb4_ro_0900_ai_ci'),260:('utf8mb4','utf8mb4_sl_0900_ai_ci'),261:('utf8mb4','utf8mb4_pl_0900_ai_ci'),262:('utf8mb4','utf8mb4_et_0900_ai_ci'),263:('utf8mb4','utf8mb4_es_0900_ai_ci'),264:('utf8mb4','utf8mb4_sv_0900_ai_ci'),265:('utf8mb4','utf8mb4_tr_0900_ai_ci'),266:('utf8mb4','utf8mb4_cs_0900_ai_ci'),267:('utf8mb4','utf8mb4_da_0900_ai_ci'),268:('utf8mb4','utf8mb4_lt_0900_ai_ci'),269:('utf8mb4','utf8mb4_sk_0900_ai_ci'),270:('utf8mb4','utf8mb4_es_trad_0900_ai_ci'),271:('utf8mb4','utf8mb4_la_0900_ai_ci'),273:('utf8mb4','utf8mb4_eo_0900_ai_ci'),274:('utf8mb4','utf8mb4_hu_0900_ai_ci'),275:('utf8mb4','utf8mb4_hr_0900_ai_ci'),277:('utf8mb4','utf8mb4_vi_0900_ai_ci'),278:('utf8mb4','utf8mb4_0900_as_cs'),279:('utf8mb4','utf8mb4_de_pb_0900_as_cs'),280:('utf8mb4','utf8mb4_is_0900_as_cs'),281:('utf8mb4','utf8mb4_lv_0900_as_cs'),282:('utf8mb4','utf8mb4_ro_0900_as_cs'),283:('utf8mb4','utf8mb4_sl_0900_as_cs'),284:('utf8mb4','utf8mb4_pl_0900_as_cs'),285:('utf8mb4','utf8mb4_et_0900_as_cs'),286:('utf8mb4','utf8mb4_es_0900_as_cs'),287:('utf8mb4','utf8mb4_sv_0900_as_cs'),288:('utf8mb4','utf8mb4_tr_0900_as_cs'),289:('utf8mb4','utf8mb4_cs_0900_as_cs'),290:('utf8mb4','utf8mb4_da_0900_as_cs'),291:('utf8mb4','utf8mb4_lt_0900_as_cs'),292:('utf8mb4','utf8mb4_sk_0900_as_cs'),293:('utf8mb4','utf8mb4_es_trad_0900_as_cs'),294:('utf8mb4','utf8mb4_la_0900_as_cs'),296:('utf8mb4','utf8mb4_eo_0900_as_cs'),297:('utf8mb4','utf8mb4_hu_0900_as_cs'),298:('utf8mb4','utf8mb4_hr_0900_as_cs'),300:('utf8mb4','utf8mb4_vi_0900_as_cs'),303:('utf8mb4','utf8mb4_ja_0900_as_cs'),304:('utf8mb4','utf8mb4_ja_0900_as_cs_ks'),305:('utf8mb4','utf8mb4_0900_as_ci'),306:('utf8mb4','utf8mb4_ru_0900_ai_ci'),307:('utf8mb4','utf8mb4_ru_0900_as_cs'),308:('utf8mb4','utf8mb4_zh_0900_as_cs'),309:('utf8mb4','utf8mb4_0900_bin')}
5 changes: 5 additions & 0 deletions ibd2sql/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#from .innodb_page import *
VERSION = (1,0)

__version__ = ".".join(str(x) for x in VERSION)

322 changes: 322 additions & 0 deletions ibd2sql/ibd2sql.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,322 @@
#!/usr/bin/env python3

import datetime
from ibd2sql.innodb_page_sdi import *
from ibd2sql.innodb_page_spaceORxdes import *
from ibd2sql.innodb_page_inode import *
from ibd2sql.innodb_page_index import *
import sys


class ibd2sql(object):
def __init__(self,*args,**kwargs):
self.LIMIT = -1
self.STATUS = False
self.PAGESIZE = 16384
#先初始化一堆信息.
self.DEBUG = False
self.DEBUG_FD = sys.stdout
self.FILENAME = ''
self.DELETE = False
self.FORCE = False
self.SET = False
self.MULTIVALUE = False
self.COMPLETE_SQL = False
self.REPLACE = False
self.WHERE1 = ''
self.WHERE2 = (0,2**48)
self.WHERE3 = (0,2**56)
self.PAGE_ID = 0
self.AUTO_DEBUG = True #自动DEBUG, 如果page解析有问题的话, 然后退出
self.SQL_PREFIX = ''
self.SQL = True
self.IS_PARTITION = False #是否为分区表

self.PAGE_MIN = 0
self.PAGE_MAX = 2**32
self.PAGE_START = -1
self.PAGE_COUNT = -1
self.PAGE_SKIP = -1


def _init_table_name(self):
try:
self.debug(f"OLD TABLENAME:{self.tablename}")
except:
pass
self.tablename = f"`{self.table.schema}`.`{self.table.table_name}`"
self.debug(f"NEW TABLENAME:{self.tablename}")
self._init_sql_prefix()

def replace_schema(self,name):
self.table.schema = name
return self._init_table_name()

def replace_name(self,name):
self.table.table_name = name
return self._init_table_name()

def read(self):
"""
RETURN PAGE RAW DATA
"""
self.debug(f"ibd2sql.read PAGE: {self.PAGE_ID} ")
self.f.seek(self.PAGESIZE*self.PAGE_ID,0)
#self.PAGE_ID += 1
return self.f.read(self.PAGESIZE)

def _init_sql_prefix(self):
#self.table.remove_virtual_column() #把虚拟字段干掉
#self.SQL_PREFIX = f"{ 'REPLACE' if self.REPLACE else 'INSERT'} INTO {self.tablename}{'(`'+'`,`'.join([ self.table.column[x]['name'] for x in self.table.column ]) + '`)' if self.COMPLETE_SQL else ''} VALUES "
SQL_PREFIX = f"{'REPLACE' if self.REPLACE else 'INSERT'} INTO {self.tablename}("
for x in self.table.column:
if self.table.column[x]['is_virtual'] or not self.COMPLETE_SQL:
continue
else:
SQL_PREFIX += f"`{self.table.column[x]['name']}`,"
SQL_PREFIX = SQL_PREFIX[:-1] + ") VALUES " if self.COMPLETE_SQL else SQL_PREFIX[:-1] + " VALUES "
self.SQL_PREFIX = SQL_PREFIX

def init(self):
self.debug("DEBUG MODE ON")
self.debug("INIT ibd2sql")
self.debug("FORCE",self.FORCE)
self.debug("SET",self.SET)
self.debug("MULTIVALUE",self.MULTIVALUE)
self.debug("AUTO_DEBUG",self.AUTO_DEBUG)
self.debug(f"FILTER: \n\t{self.WHERE1} \n\t{self.WHERE2[0]} < TRX < {self.WHERE2[1]} \n\t{self.WHERE3[0]} < ROLLPTR < {self.WHERE3[1]}")
self.STATUS = True
self.debug(f"OPEN IBD FILE:",self.FILENAME)
self.f = open(self.FILENAME,'rb')
self.PAGE_ID = 0

#first page
self.PAGE_ID = 0
self.debug("ANALYZE FIRST PAGE: FIL_PAGE_TYPE_FSP_HDR")
self.space_page = xdes(self.read()) #第一页
if not self.space_page.fsp_status:
sys.stderr.write(f"\nrow_format = compressed or its damaged or its mysql 5.7 file\n\n")
sys.exit(2)
self.debug("ANALYZE FIRST PAGE FINISH")
sdino = self.space_page.SDI_PAGE_NO
self.debug("SDI PAGE NO:",sdino)

#sdi page
if self.IS_PARTITION:
self.debug("THIS TABLE IS PARTITION TABLE")
self.tablename = "PARTITION TABLE NO NAME"
pass
else:
self.debug('ANALYZE SDI PAGE')
self.PAGE_ID = sdino
self.sdi = sdi(self.read(),debug=self.debug) #sdi页
if not self.sdi:
self.debug("ANALYZE SDI PAGE FAILED (maybe page is not 17853), will exit 2")
sys.exit(2)
self.debug('ANALYZE SDI PAGE FINISH')
self.debug('SET ibd2sql.table = sdi.table (SDI的使命已结束 >_<)')
self.table = self.sdi.table
self.tablename = self.table.name
self.debug("META INFO")
for colno in self.table.column:
self.debug(f"COLNO: {colno} \n{self.table.column[colno]}")
for idxno in self.table.index:
self.debug(f"IDXNO: {colno} \n{self.table.index[idxno]}")
self.debug("INIT SQL PREFIX")
self.debug("DDL:\n",self.table.get_ddl())
self._init_sql_prefix() #初始化表前缀, 要获取到SDI信息才能做

#inode page
self.debug(f'ANALYZE PAGE INODE (PAGE_ID=2) (for get index)')
self.PAGE_ID = 2 #inode
self.inode = inode(self.read())
self.debug("FIRST INDEX (Non-leaf and leaf page) :",self.inode.index_page[0]," (-1 is None)")
self.first_no_leaf_page = self.inode.index_page[0][0]
self.first_leaf_page = self.inode.index_page[0][1]
#self.debug("START FIND FIRST LEAF PAGE")
if self.first_leaf_page < 3 or self.first_leaf_page >= 4294967295 or True:
self.init_first_leaf_page()
self.debug("FIRST LEAF PAGE ID:",self.first_leaf_page )
self.debug("#############################################################################")
self.debug(" INIT ibd2sql FINISH ")
self.debug("#############################################################################\n\n")
return True

def init_first_leaf_page(self):
_n = 0
self.debug(f"INIT FIRST PAGE TO FIRST_NO_LEAF_PAGE ({self.first_no_leaf_page})")
self.PAGE_ID = self.first_no_leaf_page
while self.PAGE_ID < 4294967295 and self.PAGE_ID > 2:
_n += 1
self.debug(f'COUNT: {_n} FIND LEAF PAGE, CURRENT PAGE ID:',self.PAGE_ID)
aa = find_leafpage(self.read(),table=self.table, idx=self.table.cluster_index_id, debug=self.debug)
aa.pageno = self.PAGE_ID
IS_LEAF_PAGE,PAGE_ID = aa.find()
if IS_LEAF_PAGE:
self.debug("FIND FINISH, PAGE_ID:",self.PAGE_ID,'\n')
self.first_leaf_page = self.PAGE_ID
break
else:
self.first_leaf_page = self.PAGE_ID = PAGE_ID


def debug(self,*args):
if self.DEBUG:
msg = f"[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] [DEBUG] {' '.join([ str(x) for x in args ])}\n"
self.DEBUG_FD.write(msg)

def _get_index_page(self):
pn = 0
while self.PAGE_ID > 0 and self.PAGE_ID < 4294967295:
pn += 1
self.debug(f"CURRENT PAGE ID {self.PAGE_ID} PAGE NO:{pn}")
aa = page(self.read())
self.PAGE_ID = aa.FIL_PAGE_NEXT

def get_sql(self,):
self.PAGE_ID = self.PAGE_START if self.PAGE_START > 2 else self.first_leaf_page
self.MULTIVALUE = False if self.REPLACE else self.MULTIVALUE #冲突
if self.FORCE:
self.debug("============================= WARNING ================================")
self.debug("========================== FORCE IS TRUE =============================")
self.debug("============================= WARNING ================================")
self.debug("ibd2sql get_sql BEGIN:",self.PAGE_ID,self.PAGE_MIN,self.PAGE_MAX,self.PAGE_COUNT)
while self.PAGE_ID > self.PAGE_MIN and self.PAGE_ID <= self.PAGE_MAX and self.PAGE_ID < 4294967295 and self.PAGE_COUNT != 0:
self.debug("INIT INDEX OBJECT")
aa = index(self.read(),table=self.table, idx=self.table.cluster_index_id, debug=self.debug)
aa.DELETED = True if self.DELETE else False
aa.pageno = self.PAGE_ID
self.debug("SET FILTER",self.WHERE2,self.WHERE3)
aa.mintrx = self.WHERE2[0]
aa.maxtrx = self.WHERE2[1]
aa.minrollptr = self.WHERE3[0]
aa.maxrollptr = self.WHERE3[1]
self.PAGE_ID = aa.FIL_PAGE_NEXT

if self.PAGE_SKIP > 0:
self.PAGE_SKIP -= 1
self.debug("SKIP THIS PAGE")
continue
self.PAGE_COUNT -= 1

sql = self.SQL_PREFIX
if self.MULTIVALUE:
try:
_tdata = aa.read_row()
except Exception as e:
if self.FORCE:
continue
else:
self.debug(e)
break
for x in _tdata:
if self.LIMIT == 0:
return None
self.LIMIT -= 1
sql += self._tosql(x['row']) + ','
sql = (sql[:-1] + ';')
print(sql)

else:
try:
_tdata = aa.read_row()
except Exception as e:
if self.FORCE:
continue
else:
self.debug(e)
break
for x in _tdata:
if self.LIMIT == 0:
return None
self.LIMIT -= 1
_sql = f"{sql}{self._tosql(x['row'])};"
print(_sql)
if self.PAGE_COUNT == 0:
break


def test(self):
"""
TEST ONLY
"""
#self.DEBUG = False
self.debug('AUTO TEST\n\n\n##########################################################\n\t\tBEGIN TEST -_- \n##########################################################\n\n')
#self.PAGE_ID = 4
self.debug('CLUSTER INDEX ID:',self.table.cluster_index_id)
self.debug('FIRST LEAF PAGE:',self.first_leaf_page)
self.PAGE_ID = self.first_leaf_page

self.debug('ANALYZE INDEX PAGE BEGIN: (FIRST LEAF PAGE):',self.PAGE_ID)
#DATA
_n = 0

#self.replace_schema('db2')
#aa = index(self.read(),table=self.table, idx=self.table.cluster_index_id, debug=self.debug)
pc = -1 #页数限制, 方便DEBUG
sp = 2329 #跳过的page数量 也是方便DEBUG的
sp = 0
#self.PAGE_ID = 2361
self.MULTIVALUE = False if self.REPLACE else self.MULTIVALUE
while self.PAGE_ID > 0 and self.PAGE_ID < 4294967295 and pc != 0:
aa = index(self.read(),table=self.table, idx=self.table.cluster_index_id, debug=self.debug)
sp -= 1
if sp >= 0:
self.PAGE_ID = aa.FIL_PAGE_NEXT
continue
#aa = index(self.read(),table=self.table, idx=self.table.cluster_index_id, )
aa.pageno = self.PAGE_ID
aa.mintrx = self.WHERE2[0]
aa.maxtrx = self.WHERE2[1]
sql = self.SQL_PREFIX
if self.MULTIVALUE:
for x in aa.read_row():
sql += self._tosql(x['row']) + ','
_n += 1
print(sql[:-1],';')
else:
for x in aa.read_row():
print(f"{sql}{self._tosql(x['row'])};")
_n += 1
self.PAGE_ID = aa.FIL_PAGE_NEXT
pc -= 1
#break
self.debug('TOTAL ROWS:',_n)

def get_ddl(self):
return self.table.get_ddl()

def _tosql(self,row):
"""
把 row 转为SQL, 不含INSERT INTO ;等 主要是数据类型引号处理
"""
sql = '('
for colno in self.table.column:
data = row[colno]
if data is None:
sql = f"{sql}NULL, "
elif self.table.column[colno]['ct'] in ['tinyint','smallint','int','float','double','bigint','mediumint','year','decimal',] :
sql = f"{sql}{data}, "
elif (not self.SET) and (self.table.column[colno]['ct'] in ['enum','set']):
sql = f"{sql}{data}, "
elif self.table.column[colno]['ct'] == 'binary':
sql = f"{sql}{hex(data)}, " #转为16进制, 好看点,但没必要, 就int吧
else:
sql += repr(data) + ", "

return sql[:-2] + ")"

def _get_first_page(self,):
pass

def close(self):
try:
self.f.close()
except:
pass
try:
if self.DEBUG:
self.DEBUG_FD.close()
except:
pass
return True
Loading

0 comments on commit 9cbb218

Please sign in to comment.