Почему я не могу создать двух новых пользователей в SQLite, подключенных к C? Не работает на два звонка - PullRequest
0 голосов
/ 11 апреля 2020

Я не могу понять, почему это происходит. Что может быть логической ошибкой или как я могу ее решить. На самом деле проблема в том, что даже если я выполняю вход в систему клиента (здесь это не является частью кода), то при попытке входа в систему возникает такая же проблема. Но я могу сделать несколько входов и выходов. Я могу создать нового пользователя и войти в систему, используя эту

#include<stdlib.h>
#include<string.h>
#include "sqlite3.c" 
char output[5][30];//to save result
int temp;//global variable to be used in callback again
typedef struct usr{char name[15],pass[15];int uid;}USER;
static int callback(void *data, int argc, char **argv, char **azColName)
{
    int i;
    temp=argc;//stores number of return values
    printf("\n*%d*\n",argc);
    for(i=0;i<argc;i++)
    {
        strcpy(output[i],argv[i]);
        printf("*%s* ",argv[i]);
    }
    return 0;
}
void INSERTC()
{
    printf("\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tCustomer Signup");
    sqlite3 *db;
    char *zErrMsg = 0;
    int t,rc,*data;
    char sql[150],name[30],pass[30];
    printf("\n\tEnter your Username : ");
    scanf("%s",name);
    printf("\n\tEnter your Password : ");
    scanf("%s",pass);
    rc = sqlite3_open("trail1.db", &db);
    sprintf(sql, "SELECT userid FROM customer WHERE username='%s';",name);
    rc = sqlite3_exec(db, sql,callback,(void*)data, &zErrMsg);//callback is called for every line in result
    if(temp==0)
    {   
        strcpy(sql,"SELECT COUNT(*) FROM customer;");
        rc = sqlite3_exec(db, sql,callback,(void*)data, &zErrMsg);
        t=atoi(output[0]);
        sprintf(sql,"INSERT INTO customer(userid,username,password) VALUES(%d,'%s','%s');",t,name,pass);
        rc = sqlite3_exec(db, sql,callback,(void*)data, &zErrMsg);
        printf("\n\tSuccessfully Registered.\n");
        printf("\n\tUser Id Alloted : %d",t);
        sqlite3_close(db);
    }
    else
        printf("\n\tUsername already taken!");
    printf("\n\n\tPress Enter to continue...");
    getchar();getchar();
}

int main(int argc, char* argv[])
{
    INSERTC();//First call
    INSERTC();//Second call
    return 0;
}

таблицу перед выполнением кода выполнение кода

В коде, что я делаю, поиск по заданному имени пользователя и, если запрос не дал результатов, я вставляю запись. Если он вернется, он напечатает имя пользователя уже занято.

1 Ответ

0 голосов
/ 11 апреля 2020

Задача 1

Вы принимаете решение, уже занято ли имя пользователя, на основе переменной temp.

Этот параметр настроен на параметр arg c обратного вызова. Когда вы выполняете свой первый вызов INSERT C, обратный вызов для следующего оператора SELECT COUNT(*) FROM customer устанавливает temp в 1, поскольку имеется один столбец результатов COUNT(*). Фактический результат приходит в виде строки с параметром argv обратного вызова.

Документация гласит:

2-й аргумент функции обратного вызова sqlite3_exe c () - это количество столбцов в результате. Третий аргумент обратного вызова sqlite3_exe c () - это массив указателей на строки, полученных как бы из sqlite3_column_text (), по одному для каждого столбца.

см. https://www.sqlite.org/c3ref/exec.html

Задача 2

Но на самом деле кажется, что вы хотите проверить temp с помощью SELECT userid FROM customer WHERE username='%s' ранее. Но если не найдено ни одной записи с соответствующим именем пользователя, обратный вызов не вызывается.

Указатель данных

Указатель * данные никогда не инициализируются.

4-й аргумент sqlite3_exe c () передается на 1-й аргумент каждого вызова обратного вызова.

Поскольку вы не используете указатель данных, вы мог просто передать NULL. Если вы хотите использовать его, обязательно инициализируйте его.

Коды возврата

Функции sqlite3 возвращают код, который указывает, была ли операция успешной или нет. Вы должны проверить, была ли операция успешной, и предпринять соответствующие действия в случае ее сбоя (например, распечатать сообщение об ошибке в stderr и завершить кодом ошибки).

Закрытие соединения с базой данных

Вы вызываете sqlite3_close только в ветке if. Но вы должны закрыть его независимо от результатов.

Лучше использовать подготовленные операторы

Вместо того, чтобы использовать sprintf для создания собственного SQL, который содержит непроверенный внешний пользовательский ввод, вы должны использовать подготовленные операторы. Использование неконтролируемого пользовательского ввода может привести к одной из самых критических угроз безопасности, известной как SQL инъекция.

Поэтому лучше использовать sqlite3_prepare_v2 (), sqlite3_step () и sqlite3_finalize (). По сути, sqlite3_exe c - это просто удобная оболочка для этих вызовов. Для примера того, как его использовать, вы можете взглянуть на { ссылка }.

Еще одним преимуществом этого подхода будет то, что вы будете обрабатывать вызовы SQL и связанные с ними результаты. в том же месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...