popoponnponpopo’s blog

popoponnponpopo’s blog

第二の誕生

(Python,SQLite)全テーブルのレコードを昇順ソートした版のデータベースを出力

ちゃんと動くか分かりません。自分でやったらなぜかファイルサイズが違くなったのでちゃんと動いてるのかほんとわからない。

import sqlite3
import os
import sys
import codecs

#変数
errorCnt=0 
skipCnt=0  

#指定のDBの全テーブルを昇順ソートした新しいDBを「sortedDBs」というフォルダの下に作る
def makeNewSortedDB(dbname):
    #変数
    sorted="sorted-"+dbname   
    newDir="sortedDBs"         

    #確認処理
    if not os.path.exists(newDir):         
        print("「"+ newDir +"」というフォルダを作成")
        os.mkdir(newDir)                    
    if os.path.exists(newDir+"/"+sorted): 
        print("「"+dbname+"」 .....スキップ(ソート後のファイルが既に存在)")
        global skipCnt
        skipCnt=skipCnt+1
        return
    if not os.path.exists(dbname):        
        print("「"+dbname+" .....スキップ(ファイル名の指定ミス)")
        skipCnt=skipCnt+1
        return

    try:
        #DB接続&作成
        db=sqlite3.connect(dbname)              
        subdb=sqlite3.connect("sortedDBs/"+sorted)   

        #同一データ構造のデータベースを作成
        queGetTableName="SELECT name FROM sqlite_master WHERE type='table';"
        tables=db.execute(queGetTableName)          

        for table in tables.fetchall():                  
            queGetAllCREATEQuery="SELECT sql FROM sqlite_master WHERE type='table' AND name='"+table[0]+"';"
            queriesOfCREATE=db.execute(queGetAllCREATEQuery)  
            
            for queryOfCREATE in queriesOfCREATE.fetchall():   
                subdb.execute(queryOfCREATE[0])                   

        #昇順ソートしたのを新データベースにインサート
        queATTACH="ATTACH '"+dbname+"' AS originalDB;"
        subdb.execute(queATTACH)                   
        newTables=subdb.execute(queGetTableName)   

        for table in newTables.fetchall():                
            queGetFIELD="PRAGMA table_info("+escape(table[0])+");"
            fields=subdb.execute(queGetFIELD)            

            for field in fields.fetchall():         
                if(field[0] is 0):                  
                    queINSERT="INSERT INTO "+escape(table[0])+" SELECT * FROM originalDB."+escape(table[0])+" ORDER BY "+escape(field[1])+";"   
                    subdb.execute(queINSERT)      
        
        #DBクローズ
        print(dbname+" .....完了")
        closeDB(db, subdb)

    except:
        print(dbname+" .....謎のエラーにより未処理")
        closeDB(db, subdb)
        os.remove(newDir +"/"+sorted) 
        global errorCnt
        errorCnt=errorCnt+1
        
#引数に入れられた全てのDBを閉じる(可変長)
def closeDB(*inDBs):
    for db in inDBs:
        db.commit()
        db.close()    

#クエリ挿入部分をエスケープ(外人ありがとう)
def escape(s, errors="strict"):
    encodable = s.encode("utf-8", errors).decode("utf-8")
    nul_index = encodable.find("\x00")

    if nul_index >= 0:
        error = UnicodeEncodeError("NUL-terminated utf-8", encodable, nul_index, nul_index + 1, "NUL not allowed")
        error_handler = codecs.lookup_error(errors)
        replacement, _ = error_handler(error)
        encodable = encodable.replace("\x00", replacement)

    return "\"" + encodable.replace("\"", "\"\"") + "\""

#メイン処理
if __name__ =='__main__':
    #変数
    argc=len(sys.argv)    
    
    #確認処理
    if(argc<2):   
        print("\n引数が無いから入れて")
        sys.exit(1)

    #処理
    print(str(argc-1)+"個のファイルを処理します")
    for no in range(1,argc): 
        makeNewSortedDB(sys.argv[no])

    #後処理
    print("終了(エラー:"+str(errorCnt)+")(スキップ:"+str(skipCnt)+")")
        

 

ちなみになんで後半ではescape()を使わないとうまくいかなくて、前半では使うと謎のエラーが起きる(だから使ってない)のかの理由が分かってません。もう諦めました。手元のファイルでは正常動作したので動かないファイルが出てからまた悩みます。