+ /* If still within the result set */
+ if (mdb->m_row_number >= 0 && mdb->m_row_number < mdb->m_num_rows) {
+ Dmsg2(dbglvl_dbg, "sql_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->m_row_number, m_num_rows);
+
+ /* Get each value from this row */
+ for (int j = 0; j < mdb->m_num_fields; j++) {
+ mdb->m_rows[j] = PQgetvalue(mdb->m_result, mdb->m_row_number, j);
+ Dmsg2(dbglvl_dbg, "sql_fetch_row field '%d' has value '%s'\n", j, mdb->m_rows[j]);
+ }
+ mdb->m_row_number++; /* Increment the row number for the next call */
+ row = mdb->m_rows;
+ } else {
+ Dmsg2(dbglvl_dbg, "sql_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->m_row_number, m_num_rows);
+ }
+
+ Dmsg1(dbglvl_info, "sql_fetch_row finishes returning %p\n", row);
+
+ return row;
+}
+
+const char *BDB_POSTGRESQL::sql_strerror(void)
+{
+ BDB_POSTGRESQL *mdb = this;
+ return PQerrorMessage(mdb->m_db_handle);
+}
+
+void BDB_POSTGRESQL::sql_data_seek(int row)
+{
+ BDB_POSTGRESQL *mdb = this;
+ /* Set the row number to be returned on the next call to sql_fetch_row */
+ mdb->m_row_number = row;
+}
+
+int BDB_POSTGRESQL::sql_affected_rows(void)
+{
+ BDB_POSTGRESQL *mdb = this;
+ return (unsigned)str_to_int32(PQcmdTuples(mdb->m_result));
+}
+
+uint64_t BDB_POSTGRESQL::sql_insert_autokey_record(const char *query, const char *table_name)
+{
+ uint64_t id = 0;
+ char sequence[NAMEDATALEN-1];
+ char getkeyval_query[NAMEDATALEN+50];
+ PGresult *p_result;
+ BDB_POSTGRESQL *mdb = this;
+
+ /* First execute the insert query and then retrieve the currval. */
+ if (!sql_query(query)) {
+ return 0;
+ }
+
+ mdb->m_num_rows = sql_affected_rows();
+ if (mdb->m_num_rows != 1) {
+ return 0;
+ }
+ mdb->changes++;
+ /*
+ * Obtain the current value of the sequence that
+ * provides the serial value for primary key of the table.
+ *
+ * currval is local to our session. It is not affected by
+ * other transactions.
+ *
+ * Determine the name of the sequence.
+ * PostgreSQL automatically creates a sequence using
+ * <table>_<column>_seq.
+ * At the time of writing, all tables used this format for
+ * for their primary key: <table>id
+ * Except for basefiles which has a primary key on baseid.
+ * Therefore, we need to special case that one table.
+ *
+ * everything else can use the PostgreSQL formula.
+ */
+ if (strcasecmp(table_name, "basefiles") == 0) {
+ bstrncpy(sequence, "basefiles_baseid", sizeof(sequence));
+ } else {
+ bstrncpy(sequence, table_name, sizeof(sequence));
+ bstrncat(sequence, "_", sizeof(sequence));
+ bstrncat(sequence, table_name, sizeof(sequence));
+ bstrncat(sequence, "id", sizeof(sequence));
+ }