2013-11-22 5 views
0

В приведенном ниже коде работает код с комментариями.Ошибка телефонной книги SQLite

Но с использованием метода saveDataDBMgr Результаты класса «Не удалось добавить контакт».

Я хочу видеть вместо этого «Contact added».

-(void) saveData{  
    NSString *insSQL = [NSString stringWithFormat:@"INSERT INTO CONTACTS (name,address,phone) VALUES (\"%@\",\"%@\",\"%@\")",name.text,address.text,phone.text]; 

    DBMgr *dbmgr = [DBMgr alloc]; 

    if([dbmgr saveData:insSQL]== 0){ 
    status.text = @"Contact added"; 
    }else if([dbmgr saveData:insSQL]== 1){ 
    [email protected]"Failded to add contact"; 
    } 

    /*sqlite3_stmt *statement; 
    const char *dbpath = [databasePath UTF8String]; 

    if(sqlite3_open(dbpath, &contactDB) == SQLITE_OK) 
    { 
     NSString *insertSQL = [NSString stringWithFormat:@"INSERT INTO CONTACTS (name,address,phone) VALUES (\"%@\",\"%@\",\"%@\")",name.text,address.text,phone.text]; 

     const char *insert_stmt = [insertSQL UTF8String]; 
     sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL); 

     if(sqlite3_step(statement) == SQLITE_DONE) 
     { 
      status.text = @"Contact added"; 
      name.text = @""; 
      address.text = @""; 
      phone.text = @""; 
     }else{ 
      [email protected]"Failded to add contact"; 
     } 
     sqlite3_finalize(statement); 
     sqlite3_close(contactDB); 

    }*/ 
} 

-(NSInteger) saveData:(NSString *) querySQL{ 
    NSInteger result; 
    sqlite3_stmt *statement; 
    const char *dbpath = [databasePath UTF8String]; 

    if(sqlite3_open(dbpath, &contactDB) == SQLITE_OK) 
    { 
     NSString *insertSQL = querySQL; 

     const char *insert_stmt = [insertSQL UTF8String]; 

     sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL); 

     if(sqlite3_step(statement) == SQLITE_DONE) 
     { 
      result = 0; 
     }else{ 
      result = 1; 
     } 
     sqlite3_finalize(statement); 
     sqlite3_close(contactDB); 
    } 
    return result; 
} 
+1

Я не знаю, что такое класс «DBMgr», но, возможно, вам нужно сделать «DBMgr» dbmgr = [[DBMgr alloc] init]; 'вместо просто« alloc ». – Anna

ответ

1

Вы должны проверить результат коды всех ваших SQLite вызовов, и если они терпят неудачу, зарегистрировать ошибку:

- (NSInteger) saveData:(NSString *) querySQL{ 
    NSInteger result = 1; 
    sqlite3_stmt *statement; 
    const char *dbpath = [databasePath UTF8String]; 

    if(sqlite3_open(dbpath, &contactDB) == SQLITE_OK) 
    { 
     NSString *insertSQL = querySQL; 

     const char *insert_stmt = [insertSQL UTF8String]; 

     if (sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL) != SQLITE_OK) 
      NSLog(@"%s: prepare failed: %s", __FUNCTION__, sqlite3_errmsg(contactDB)); 
     else 
     { 
      if(sqlite3_step(statement) == SQLITE_DONE) 
      { 
       result = 0; 
      }else{ 
       NSLog(@"%s: step failed: %s", __FUNCTION__, sqlite3_errmsg(contactDB)); 
      } 
      sqlite3_finalize(statement); 
     } 

     sqlite3_close(contactDB); 
    } else { 
     NSLog(@"%s: open failed", __FUNCTION__); 
    } 

    return result; 
} 

Если вы не смотрите на sqlite3_errmsg, вы только гадать. И проверьте код возврата sqlite3_prepare_v2 тоже, как я сделал выше, (поскольку это скорее будет начальным указанием проблемы).


Два других, не связанных между собой, наблюдения:

  1. DBMgr должен быть инициализирован, например .:

    DBMgr *dbmgr = [[DBMgr alloc] init]; 
    
  2. Вы строите INSERT оператор с stringWithFormat. Это очень опасно, вы должны использовать ? заполнителей в вашем SQL:

    const char *insSQL = "INSERT INTO CONTACTS (name,address,phone) VALUES (?, ?, ?)"; 
    sqlite3_prepare_v2(contactDB, insSQL, -1, &statement, NULL); 
    

    Затем, после подготовки этого заявления, то вы должны использовать функцию sqlite3_bind_text, чтобы назначить значения этих трех заполнителей, например

    sqlite3_bind_text(statement, 1, [name.text UTF8String], -1, SQLITE_TRANSIENT); 
    sqlite3_bind_text(statement, 2, [address.text UTF8String], -1, SQLITE_TRANSIENT); 
    sqlite3_bind_text(statement, 3, [phone.text UTF8String], -1, SQLITE_TRANSIENT); 
    

    Кстати, если вы хотите, чтобы указать NULL, вы назвали бы sqlite3_bind_null вместо sqlite3_bind_text.

    Очевидно, проверьте код возврата из каждого из них, чтобы убедиться, что вы вернули SQLITE_OK для каждого, опять же, регистрацию sqlite3_errmsg, если это не удалось.

    Я ценю, что это изменение потребует некоторого рефакторинга вашего кода, но важно использовать sqlite3_bind_text, чтобы избежать атак SQL-инъекций и ошибок, которые могут возникнуть, если пользователь ввел значение, включающее кавычки.

Кстати, если вы смотрите на выше и понимая, что она занимает много кода, чтобы сделать это правильно, вы можете рассмотреть вопрос об использовании FMDB, которые могут значительно упростить вашу жизнь.

+0

thx !! Я решаю проблему !!!!! причина ..

'- (недействительными) initDB: (NSString *) DBPATH: (sqlite3 *) contDB {
self.databasePath = DBPATH;
self.contactDB = contDB;
} ' – HighCho

+0

Я рад, что вы решили свою проблему.BTW, не забудьте вызвать '[super init]'. – Rob

Смежные вопросы