From ed89adc8a1d40dda9739903ae7341485ba356487 Mon Sep 17 00:00:00 2001 From: Marco van Wieringen Date: Mon, 5 Apr 2010 18:53:04 +0200 Subject: [PATCH] Make sql_insert_id a atomic function which executes the insert query and when that succeeds retrieves the id the database used for storing the inserted record. Some databases want this to be atomic (e.g. without a COMMIT in between.) Coding wise this is also much cleaner. --- bacula/src/cats/cats.h | 111 ++++++++++++++++++----------------- bacula/src/cats/dbi.c | 25 +++++++- bacula/src/cats/ingres.c | 21 ++++++- bacula/src/cats/mysql.c | 20 +++++++ bacula/src/cats/postgresql.c | 21 ++++++- bacula/src/cats/sql_create.c | 53 +++++++---------- bacula/src/cats/sqlite.c | 23 ++++++++ 7 files changed, 183 insertions(+), 91 deletions(-) diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 164eec325c..f4e49f6dcb 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -159,27 +159,26 @@ struct B_DB { * * S Q L I T E */ -#define sql_store_result(x) (x)->result -#define sql_free_result(x) my_sqlite_free_table(x) -#define sql_fetch_row(x) my_sqlite_fetch_row(x) -#define sql_query(x, y) my_sqlite_query((x), (y)) +#define sql_store_result(x) (x)->result +#define sql_free_result(x) my_sqlite_free_table(x) +#define sql_fetch_row(x) my_sqlite_fetch_row(x) +#define sql_query(x, y) my_sqlite_query((x), (y)) +#define sql_insert_id(x, y, z) my_sqlite_sql_insert_id((x), (y), (z)) #ifdef HAVE_SQLITE3 -#define sql_insert_id(x,y) sqlite3_last_insert_rowid((x)->db) -#define sql_close(x) sqlite3_close((x)->db) -#define sql_affected_rows(x) sqlite3_changes((x)->db) +#define sql_close(x) sqlite3_close((x)->db) +#define sql_affected_rows(x) sqlite3_changes((x)->db) #else -#define sql_insert_id(x,y) sqlite_last_insert_rowid((x)->db) -#define sql_close(x) sqlite_close((x)->db) -#define sql_affected_rows(x) 1 +#define sql_close(x) sqlite_close((x)->db) +#define sql_affected_rows(x) 1 #endif -#define sql_strerror(x) (x)->sqlite_errmsg?(x)->sqlite_errmsg:"unknown" -#define sql_num_rows(x) (x)->nrow -#define sql_data_seek(x, i) (x)->row = (i) -#define sql_field_seek(x, y) my_sqlite_field_seek((x), (y)) -#define sql_fetch_field(x) my_sqlite_fetch_field(x) -#define sql_num_fields(x) ((x)->ncolumn) -#define SQL_ROW char** -#define SQL_MATCH "MATCH" +#define sql_strerror(x) (x)->sqlite_errmsg?(x)->sqlite_errmsg:"unknown" +#define sql_num_rows(x) (x)->nrow +#define sql_data_seek(x, i) (x)->row = (i) +#define sql_field_seek(x, y) my_sqlite_field_seek((x), (y)) +#define sql_fetch_field(x) my_sqlite_fetch_field(x) +#define sql_num_fields(x) ((x)->ncolumn) +#define SQL_ROW char** +#define SQL_MATCH "MATCH" #define sql_batch_start(x,y) my_batch_start(x,y) #define sql_batch_end(x,y,z) my_batch_end(x,y,z) @@ -196,6 +195,7 @@ SQL_ROW my_sqlite_fetch_row(B_DB *mdb); int my_sqlite_query(B_DB *mdb, const char *cmd); void my_sqlite_field_seek(B_DB *mdb, int field); SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb); +int my_sqlite_sql_insert_id(B_DB *mdb, const char *query, const char *table_name); extern const char* my_sqlite_batch_lock_query; extern const char* my_sqlite_batch_unlock_query; extern const char* my_sqlite_batch_fill_filename_query; @@ -381,22 +381,22 @@ struct B_DB { #define DB_STATUS int /* "Generic" names for easier conversion */ -#define sql_store_result(x) mysql_store_result((x)->db) -#define sql_use_result(x) mysql_use_result((x)->db) -#define sql_free_result(x) my_mysql_free_result(x) -#define sql_fetch_row(x) mysql_fetch_row((x)->result) -#define sql_query(x, y) mysql_query((x)->db, (y)) -#define sql_strerror(x) mysql_error((x)->db) -#define sql_num_rows(x) mysql_num_rows((x)->result) -#define sql_data_seek(x, i) mysql_data_seek((x)->result, (i)) -#define sql_affected_rows(x) mysql_affected_rows((x)->db) -#define sql_insert_id(x,y) mysql_insert_id((x)->db) -#define sql_field_seek(x, y) mysql_field_seek((x)->result, (y)) -#define sql_fetch_field(x) mysql_fetch_field((x)->result) -#define sql_num_fields(x) (int)mysql_num_fields((x)->result) -#define SQL_ROW MYSQL_ROW -#define SQL_FIELD MYSQL_FIELD -#define SQL_MATCH "MATCH" +#define sql_store_result(x) mysql_store_result((x)->db) +#define sql_use_result(x) mysql_use_result((x)->db) +#define sql_free_result(x) my_mysql_free_result(x) +#define sql_fetch_row(x) mysql_fetch_row((x)->result) +#define sql_query(x, y) mysql_query((x)->db, (y)) +#define sql_strerror(x) mysql_error((x)->db) +#define sql_num_rows(x) mysql_num_rows((x)->result) +#define sql_data_seek(x, i) mysql_data_seek((x)->result, (i)) +#define sql_affected_rows(x) mysql_affected_rows((x)->db) +#define sql_insert_id(x, y, z) my_mysql_sql_insert_id((x), (y), (z)) +#define sql_field_seek(x, y) mysql_field_seek((x)->result, (y)) +#define sql_fetch_field(x) mysql_fetch_field((x)->result) +#define sql_num_fields(x) (int)mysql_num_fields((x)->result) +#define SQL_ROW MYSQL_ROW +#define SQL_FIELD MYSQL_FIELD +#define SQL_MATCH "MATCH" #define sql_batch_start(x,y) my_batch_start(x,y) #define sql_batch_end(x,y,z) my_batch_end(x,y,z) @@ -414,6 +414,7 @@ extern const char* my_mysql_batch_unlock_tables_query; extern const char* my_mysql_batch_fill_filename_query; extern const char* my_mysql_batch_fill_path_query; extern void my_mysql_free_result(B_DB *mdb); +extern int my_mysql_sql_insert_id(B_DB *mdb, const char *query, const char *table_name); #else @@ -485,7 +486,7 @@ void my_postgresql_free_result(B_DB *mdb); POSTGRESQL_ROW my_postgresql_fetch_row (B_DB *mdb); int my_postgresql_query (B_DB *mdb, const char *query); void my_postgresql_data_seek (B_DB *mdb, int row); -int my_postgresql_currval (B_DB *mdb, const char *table_name); +int my_postgresql_insert_id (B_DB *mdb, const char *query, const char *table_name) void my_postgresql_field_seek (B_DB *mdb, int row); POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb); @@ -511,7 +512,7 @@ extern const char* my_pg_batch_fill_path_query; #define sql_num_rows(x) ((unsigned) PQntuples((x)->result)) #define sql_data_seek(x, i) my_postgresql_data_seek((x), (i)) #define sql_affected_rows(x) ((unsigned) atoi(PQcmdTuples((x)->result))) -#define sql_insert_id(x,y) my_postgresql_currval((x), (y)) +#define sql_insert_id(x, y, z) my_postgresql_insert_id((x), (y), (z)) #define sql_field_seek(x, y) my_postgresql_field_seek((x), (y)) #define sql_fetch_field(x) my_postgresql_fetch_field(x) #define sql_num_fields(x) ((x)->num_fields) @@ -595,10 +596,10 @@ void my_ingres_free_result(B_DB *mdb); INGRES_ROW my_ingres_fetch_row (B_DB *mdb); int my_ingres_query (B_DB *mdb, const char *query); void my_ingres_data_seek (B_DB *mdb, int row); -int my_ingres_currval (B_DB *mdb, const char *table_name); void my_ingres_field_seek (B_DB *mdb, int row); INGRES_FIELD * my_ingres_fetch_field(B_DB *mdb); void my_ingres_close (B_DB *mdb); +int my_ingres_insert_id (B_DB *mdb, const char *query, const char *table_name); int my_ingres_batch_start(JCR *jcr, B_DB *mdb); int my_ingres_batch_end(JCR *jcr, B_DB *mdb, const char *error); @@ -613,19 +614,19 @@ extern const char* my_ingres_batch_fill_filename_query; extern const char* my_ingres_batch_fill_path_query; /* "Generic" names for easier conversion */ -#define sql_store_result(x) ((x)->result) -#define sql_free_result(x) my_ingres_free_result(x) -#define sql_fetch_row(x) my_ingres_fetch_row(x) -#define sql_query(x, y) my_ingres_query((x), (y)) -#define sql_close(x) my_ingres_close(x) -#define sql_strerror(x) INGerrorMessage((x)->db) -#define sql_num_rows(x) ((unsigned) INGntuples((x)->result)) -#define sql_data_seek(x, i) my_ingres_data_seek((x), (i)) -#define sql_affected_rows(x) ((unsigned) atoi(INGcmdTuples((x)->result))) -#define sql_insert_id(x,y) my_ingres_currval((x), (y)) -#define sql_field_seek(x, y) my_ingres_field_seek((x), (y)) -#define sql_fetch_field(x) my_ingres_fetch_field(x) -#define sql_num_fields(x) ((x)->num_fields) +#define sql_store_result(x) ((x)->result) +#define sql_free_result(x) my_ingres_free_result(x) +#define sql_fetch_row(x) my_ingres_fetch_row(x) +#define sql_query(x, y) my_ingres_query((x), (y)) +#define sql_close(x) my_ingres_close(x) +#define sql_strerror(x) INGerrorMessage((x)->db) +#define sql_num_rows(x) ((unsigned) INGntuples((x)->result)) +#define sql_data_seek(x, i) my_ingres_data_seek((x), (i)) +#define sql_affected_rows(x) ((x)->num_rows) +#define sql_insert_id(x, y, z) my_ingres_insert_id((x), (y), (z)) +#define sql_field_seek(x, y) my_ingres_field_seek((x), (y)) +#define sql_fetch_field(x) my_ingres_fetch_field(x) +#define sql_num_fields(x) ((x)->num_fields) #define sql_batch_start(x,y) my_ingres_batch_start(x,y) #define sql_batch_end(x,y,z) my_ingres_batch_end(x,y,z) @@ -727,7 +728,7 @@ const char * my_dbi_strerror (B_DB *mdb); int my_dbi_getisnull (dbi_result *result, int row_number, int column_number); char * my_dbi_getvalue (dbi_result *result, int row_number, unsigned int column_number); //int my_dbi_getvalue (dbi_result *result, int row_number, unsigned int column_number, char *value); -int my_dbi_sql_insert_id(B_DB *mdb, char *table_name); +int my_dbi_sql_insert_id(B_DB *mdb, const char *query, const char *table_name); int my_dbi_batch_start(JCR *jcr, B_DB *mdb); int my_dbi_batch_end(JCR *jcr, B_DB *mdb, const char *error); @@ -758,10 +759,10 @@ extern const char* my_dbi_match[4]; #define SQL_MATCH my_dbi_match[db_type] /* #define sql_affected_rows(x) dbi_result_get_numrows_affected((x)->result) */ #define sql_affected_rows(x) 1 -#define sql_insert_id(x,y) my_dbi_sql_insert_id((x), (y)) -#define sql_field_seek(x, y) my_dbi_field_seek((x), (y)) -#define sql_fetch_field(x) my_dbi_fetch_field(x) -#define sql_num_fields(x) ((x)->num_fields) +#define sql_insert_id(x, y, z) my_dbi_sql_insert_id((x), (y), (z)) +#define sql_field_seek(x, y) my_dbi_field_seek((x), (y)) +#define sql_fetch_field(x) my_dbi_fetch_field(x) +#define sql_num_fields(x) ((x)->num_fields) #define sql_batch_start(x,y) my_dbi_batch_start(x,y) #define sql_batch_end(x,y,z) my_dbi_batch_end(x,y,z) #define sql_batch_insert(x,y,z) my_dbi_batch_insert(x,y,z) diff --git a/bacula/src/cats/dbi.c b/bacula/src/cats/dbi.c index f721f1fbb2..eb77308562 100644 --- a/bacula/src/cats/dbi.c +++ b/bacula/src/cats/dbi.c @@ -1221,7 +1221,7 @@ char *my_dbi_getvalue(dbi_result *result, int row_number, unsigned int column_nu return buf; } -int my_dbi_sql_insert_id(B_DB *mdb, char *table_name) +static int my_dbi_sequence_last(B_DB *mdb, char *table_name) { /* Obtain the current value of the sequence that @@ -1241,8 +1241,8 @@ int my_dbi_sql_insert_id(B_DB *mdb, char *table_name) everything else can use the PostgreSQL formula. */ - char sequence[30]; - uint64_t id = 0; + char sequence[30]; + uint64_t id = 0; if (mdb->db_type == SQL_TYPE_POSTGRESQL) { @@ -1264,6 +1264,25 @@ int my_dbi_sql_insert_id(B_DB *mdb, char *table_name) return id; } +int my_dbi_sql_insert_id(B_DB *mdb, const char *query, const char *table_name) +{ + /* + * First execute the insert query and then retrieve the currval. + */ + if (!my_dbi_query(mdb, query)) { + return 0; + } + + mdb->num_rows = sql_affected_rows(mdb); + if (mdb->num_rows != 1) { + return 0; + } + + mdb->changes++; + + return my_dbi_sequence_last(mdb, table_name); +} + #ifdef HAVE_BATCH_FILE_INSERT const char *my_dbi_batch_lock_path_query[4] = { /* Mysql */ diff --git a/bacula/src/cats/ingres.c b/bacula/src/cats/ingres.c index bc32703a0f..e9ea6abee6 100755 --- a/bacula/src/cats/ingres.c +++ b/bacula/src/cats/ingres.c @@ -632,7 +632,7 @@ void my_ingres_free_result(B_DB *mdb) db_unlock(mdb); } -int my_ingres_currval(B_DB *mdb, const char *table_name) +static int my_ingres_currval(B_DB *mdb, const char *table_name) { /* * Obtain the current value of the sequence that @@ -674,6 +674,25 @@ bail_out: return id; } +int my_ingres_insert_id(B_DB *mdb, const char *query, const char *table_name) +{ + /* + * First execute the insert query and then retrieve the currval. + * By setting transaction to true we make it an atomic transaction + * and as such we can get the currval after which we commit if + * mdb->transaction is false. This way its an atomic operation for + * Ingres and things work. + */ + mdb->num_rows = INGexec(mdb->db, new_query, true); + if (INGcheck()) { + return 0; + } + + mdb->changes++; + + return my_ingres_currval(mdb, table_name); +} + #ifdef HAVE_BATCH_FILE_INSERT int my_ingres_batch_start(JCR *jcr, B_DB *mdb) { diff --git a/bacula/src/cats/mysql.c b/bacula/src/cats/mysql.c index 1045d24c5d..0d079ae058 100644 --- a/bacula/src/cats/mysql.c +++ b/bacula/src/cats/mysql.c @@ -373,6 +373,26 @@ void my_mysql_free_result(B_DB *mdb) db_unlock(mdb); } +int my_mysql_sql_insert_id(B_DB *mdb, const char *query, const char *table_name) +{ + /* + * First execute the insert query and then retrieve the currval. + */ + if (!mysql_query(mdb, query)) { + return 0; + } + + mdb->num_rows = sql_affected_rows(mdb); + if (mdb->num_rows != 1) { + return 0; + } + + mdb->changes++; + + return mysql_insert_id(mdb->db); +} + + #ifdef HAVE_BATCH_FILE_INSERT const char *my_mysql_batch_lock_path_query = "LOCK TABLES Path write, batch write, Path as p write"; diff --git a/bacula/src/cats/postgresql.c b/bacula/src/cats/postgresql.c index 693b009d39..9b208ab27b 100644 --- a/bacula/src/cats/postgresql.c +++ b/bacula/src/cats/postgresql.c @@ -586,7 +586,7 @@ void my_postgresql_free_result(B_DB *mdb) db_unlock(mdb); } -int my_postgresql_currval(B_DB *mdb, const char *table_name) +static int my_postgresql_currval(B_DB *mdb, const char *table_name) { // Obtain the current value of the sequence that // provides the serial value for primary key of the table. @@ -651,6 +651,25 @@ bail_out: return id; } +int my_postgresql_insert_id(B_DB *mdb, const char *query, const char *table_name) +{ + /* + * First execute the insert query and then retrieve the currval. + */ + if (!my_postgresql_query(mdb, query)) { + return 0; + } + + mdb->num_rows = sql_affected_rows(mdb); + if (mdb->num_rows != 1) { + return 0; + } + + mdb->changes++; + + return my_postgresql_currval(mdb, table_name); +} + #ifdef HAVE_BATCH_FILE_INSERT int my_postgresql_batch_start(JCR *jcr, B_DB *mdb) diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 0eb2fbc5f0..0508351cdb 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -90,13 +90,12 @@ db_create_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) (char)(jr->JobStatus), dt, edit_uint64(JobTDate, ed1), edit_int64(jr->ClientId, ed2)); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + jr->JobId = sql_insert_id(mdb, mdb->cmd, NT_("Job")); + if (jr->JobId == 0) { Mmsg2(&mdb->errmsg, _("Create DB Job record %s failed. ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); - jr->JobId = 0; ok = false; } else { - jr->JobId = sql_insert_id(mdb, NT_("Job")); ok = true; } db_unlock(mdb); @@ -208,13 +207,12 @@ db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) pr->ActionOnPurge ); Dmsg1(200, "Create Pool: %s\n", mdb->cmd); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + pr->PoolId = sql_insert_id(mdb, mdb->cmd, NT_("Pool")); + if (pr->PoolId == 0) { Mmsg2(&mdb->errmsg, _("Create db Pool record %s failed: ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); - pr->PoolId = 0; stat = false; } else { - pr->PoolId = sql_insert_id(mdb, NT_("Pool")); stat = true; } db_unlock(mdb); @@ -255,13 +253,12 @@ db_create_device_record(JCR *jcr, B_DB *mdb, DEVICE_DBR *dr) edit_uint64(dr->MediaTypeId, ed1), edit_int64(dr->StorageId, ed2)); Dmsg1(200, "Create Device: %s\n", mdb->cmd); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + dr->DeviceId = sql_insert_id(mdb, mdb->cmd, NT_("Device")); + if (dr->DeviceId == 0) { Mmsg2(&mdb->errmsg, _("Create db Device record %s failed: ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); - dr->DeviceId = 0; ok = false; } else { - dr->DeviceId = sql_insert_id(mdb, NT_("Device")); ok = true; } db_unlock(mdb); @@ -314,13 +311,13 @@ bool db_create_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr) Mmsg(mdb->cmd, "INSERT INTO Storage (Name,AutoChanger)" " VALUES ('%s',%d)", sr->Name, sr->AutoChanger); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + sr->StorageId = sql_insert_id(mdb, mdb->cmd, NT_("Storage")); + if (sr->StorageId == 0) { Mmsg2(&mdb->errmsg, _("Create DB Storage record %s failed. ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); ok = false; } else { - sr->StorageId = sql_insert_id(mdb, NT_("Storage")); sr->created = true; ok = true; } @@ -362,13 +359,12 @@ db_create_mediatype_record(JCR *jcr, B_DB *mdb, MEDIATYPE_DBR *mr) mr->MediaType, mr->ReadOnly); Dmsg1(200, "Create mediatype: %s\n", mdb->cmd); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + mr->MediaTypeId = sql_insert_id(mdb, mdb->cmd, NT_("MediaType")); + if (mr->MediaTypeId == 0) { Mmsg2(&mdb->errmsg, _("Create db mediatype record %s failed: ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); - mr->MediaTypeId = 0; stat = false; } else { - mr->MediaTypeId = sql_insert_id(mdb, NT_("MediaType")); stat = true; } db_unlock(mdb); @@ -442,12 +438,12 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) Dmsg1(500, "Create Volume: %s\n", mdb->cmd); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + mr->MediaId = sql_insert_id(mdb, mdb->cmd), NT_("Media")); + if (mr->MediaId == 0) { Mmsg2(&mdb->errmsg, _("Create DB Media record %s failed. ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); stat = 0; } else { - mr->MediaId = sql_insert_id(mdb, NT_("Media")); stat = 1; if (mr->set_label_date) { char dt[MAX_TIME_LENGTH]; @@ -521,14 +517,13 @@ int db_create_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr) edit_uint64(cr->FileRetention, ed1), edit_uint64(cr->JobRetention, ed2)); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + cr->ClientId = sql_insert_id(mdb, mdb->cmd, NT_("Client")); + if (cr->ClientId == 0) { Mmsg2(&mdb->errmsg, _("Create DB Client record %s failed. ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); - cr->ClientId = 0; stat = 0; } else { - cr->ClientId = sql_insert_id(mdb, NT_("Client")); stat = 1; } db_unlock(mdb); @@ -587,14 +582,14 @@ int db_create_path_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) Mmsg(mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", mdb->esc_name); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + ar->PathId = sql_insert_id(mdb, mdb->cmd, NT_("Path")); + if (ar->PathId == 0) { Mmsg2(&mdb->errmsg, _("Create db Path record %s failed. ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); ar->PathId = 0; stat = 0; } else { - ar->PathId = sql_insert_id(mdb, NT_("Path")); stat = 1; } @@ -700,14 +695,13 @@ bool db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) Mmsg(mdb->cmd, "INSERT INTO FileSet (FileSet,MD5,CreateTime) " "VALUES ('%s','%s','%s')", fsr->FileSet, fsr->MD5, fsr->cCreateTime); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + fsr->FileSetId = sql_insert_id(mdb, mdb->cmd, NT_("FileSet")); + if (fsr->FileSetId == 0) { Mmsg2(&mdb->errmsg, _("Create DB FileSet record %s failed. ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); - fsr->FileSetId = 0; stat = false; } else { - fsr->FileSetId = sql_insert_id(mdb, NT_("FileSet")); fsr->created = true; stat = true; } @@ -1023,14 +1017,13 @@ static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId, ar->attr, digest); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + ar->FileId = sql_insert_id(mdb, mdb->cmd, NT_("File")); + if (ar->FileId == 0) { Mmsg2(&mdb->errmsg, _("Create db File record %s failed. ERR=%s"), mdb->cmd, sql_strerror(mdb)); Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); - ar->FileId = 0; stat = 0; } else { - ar->FileId = sql_insert_id(mdb, NT_("File")); stat = 1; } return stat; @@ -1071,13 +1064,11 @@ static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) Mmsg(mdb->cmd, "INSERT INTO Filename (Name) VALUES ('%s')", mdb->esc_name); - if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + ar->FilenameId = sql_insert_id(mdb, mdb->cmd, NT_("Filename")); + if (ar->FilenameId == 0) { Mmsg2(&mdb->errmsg, _("Create db Filename record %s failed. ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); - ar->FilenameId = 0; - } else { - ar->FilenameId = sql_insert_id(mdb, NT_("Filename")); } return ar->FilenameId > 0; } diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index 84c33a2155..df42efdef5 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -491,6 +491,29 @@ SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb) } } +int my_sqlite_sql_insert_id(B_DB *mdb, const char *query, const char *table_name) +{ + /* + * First execute the insert query and then retrieve the currval. + */ + if (!my_sqlite_query(mdb, query)) { + return 0; + } + + mdb->num_rows = sql_affected_rows(mdb); + if (mdb->num_rows != 1) { + return 0; + } + + mdb->changes++; + +#ifdef HAVE_SQLITE3 + return sqlite3_last_insert_rowid(mdb->db); +#else + return sqlite_last_insert_rowid(mdb->db); +#endif +} + #ifdef HAVE_BATCH_FILE_INSERT const char *my_sqlite_batch_lock_query = "BEGIN"; const char *my_sqlite_batch_unlock_query = "COMMIT"; -- 2.39.5