2016-12-28 3 views
1

データベースに100000を超えるデータを挿入して更新しています。私はlibsqlite3フレームワークを使用しています。メモリに問題がありました。データベースにデータを再帰的に挿入して更新します。

問題:私は直面しているそれぞれの挿入メモリの増加は、4-5メガバイトに増加し、決して解放されます。より良い解決策はありますか?

class DataBase{ 

let COMPANY_TABLE_NAME = "CompanyTable" 

let fileName = "\(Constants.sharedInstance.DATABASE_NAME).sqlite" 
let DBPath :String? 

init() { 

    DBPath = FileManagement.sharedInstance.getDocumentFilePath(fileName) 
} 

private var dbPointer: OpaquePointer? 

    let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self) 
    let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self) 



deinit 
{ 
    sqlite3_close(dbPointer) 

} 

    func openDataBase(dbPath:String) -> OpaquePointer { 


    var db: OpaquePointer? 

    if sqlite3_open(dbPath, &db) == SQLITE_OK 
    { 
     print("Successfully opened connection to database at \(dbPath)") 
    } 
    else 
    { 
     //call to load database from file system 
    } 
    return db! 
} 


func inserttoCompanyTable(org_code: String , dataString:String) 
{ 


    let insertSql = "INSERT INTO CompanyTable(orgcode,company_data) VALUES (?,?)" 

    let insertStatement = prepareStatement(sql: insertSql) 

    sqlite3_bind_text(insertStatement, 0, org_code, -1, SQLITE_TRANSIENT) 
    sqlite3_bind_text(insertStatement, 1, dataString, -1,SQLITE_TRANSIENT) 


    if sqlite3_step(insertStatement) != SQLITE_DONE { 

     let errmsg = String(cString: sqlite3_errmsg(insertStatement)) 
     print("failure inserting foo: \(errmsg)") 
    } 

    sqlite3_finalize(insertStatement) 
    sqlite3_close_v2(insertStatement) 
} 


func readAllData()-> [Company] 
{ 

    var companiesArray:[Company] = [Company]() 
    let selectQuery = "SELECT * FROM \(COMPANY_TABLE_NAME);" 
    let selectStatement = prepareStatement(sql: selectQuery) 

    while sqlite3_step(selectStatement) == SQLITE_ROW { 

     if let comStr = sqlite3_column_text(selectStatement, 1) 
     { 
     let comString = String(describing: comStr) 

     let comOBj = Mapper<Company>().map(JSONString: comString) 
     companiesArray.append(comOBj!) 
     } 

    } 

    return companiesArray 
} 


func isCompanyAvailable(org_code:String) -> Bool { 



    let selectQuery = "SELECT * FROM \(COMPANY_TABLE_NAME) WHERE \(CompanyTable.orgcode) =?;" 
    let selectStatement = prepareStatement(sql: selectQuery) 

    sqlite3_bind_text(selectStatement, 0, org_code, -1, SQLITE_TRANSIENT) 

    if sqlite3_step(selectStatement) == SQLITE_ROW 
    { 
     return true 
    } 
    else 
    { 
     return false 
    } 



} 


func updateTableData(company: Company)-> Bool { 

    let objString = company.toJSONString() 
    let updateQuery = "UPDATE TABLE \(COMPANY_TABLE_NAME) SET \(CompanyTable.company_data) = \(objString) WHERE \(CompanyTable.orgcode) = \(company.orgCode);" 
    let updateStatement = prepareStatement(sql: updateQuery) 

    if sqlite3_step(updateStatement) == SQLITE_ROW 
    { 
     return true 
    } 
    else 
    { 
     return false 
    } 

} 


func deleteFromCompanyTable(company:Company) { 

    let deleteQuery = "DELETE FROM \(COMPANY_TABLE_NAME) WHERE \(CompanyTable.orgcode) = \(company.orgCode);" 
    let deleteStatement = prepareStatement(sql: deleteQuery) 

    if sqlite3_step(deleteStatement) == SQLITE_DONE 
    { 
     print("Successfully deleted row.") 
    } else { 

     print("Could not delete row.") 
    } 

} 

func prepareStatement(sql: String) -> OpaquePointer { 
    var statement: OpaquePointer? 


    if sqlite3_open(DBPath, &self.dbPointer) == SQLITE_OK 
    { 
     print("Successfully opened connection to database at \(DBPath)") 
     if sqlite3_prepare_v2(self.dbPointer, sql, -1, &statement, nil) == SQLITE_OK 
     { 

      return statement! 
     } 
     else 
     { 
      let errmsg = String(cString: sqlite3_errmsg(statement)) 
      print("error preparing select: \(errmsg)") 
     } 
    } 


    return statement! 
} 
+0

'sqlite3_finalize'を正しく呼び出す場所、つまり' inserttoCompanyTable'では、その文で 'sqlite3_close_v2'を呼び出すのは間違っています。文を「閉じる」べきではありません。それだけで "ファイナライズ"し、そのステートメントで完了です。文章ではなく、データベースを閉じます。 – Rob

+0

'sqlite3_bind_XXX'呼び出しは0から始まるインデックスではなく、1から始まるインデックスを取ることにも注意してください。 'sqlite3_column_XXX'呼び出しはゼロベースのインデックスを使用しますが、' sqlite3_bind_XXX' APIは使用しません。 – Rob

答えて

0

あなたsqlite3_prepare_v2通話のほとんどは、対応するsqlite3_finalize呼び出しが続いていないので、あなたはメモリリークが発生します。 SQLステートメントを正常に準備するたびに、そのステートメントを完了した時点で確実に確定する必要があります。

関連する問題