]> www.infradead.org Git - users/mchehab/rasdaemon.git/commitdiff
rasdaemon: fix for the ras-record.c:ras_mc_prepare_stmt() failure when new fields...
authorShiju Jose <shiju.jose@huawei.com>
Wed, 13 Nov 2019 16:31:12 +0000 (16:31 +0000)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Wed, 20 Nov 2019 04:16:24 +0000 (05:16 +0100)
rasdaemon fails in the ras_mc_prepare_stmt() function when new fields are
added to the table's db_fields on top of the existing sql table in the
system.

This patch adds solution for this issue.

Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
ras-record.c

index c6cf61af8d590997bfb8abfffa0c2c645c725105..ca58b228fa93a1b157805fe8e8f6f315e8000929 100644 (file)
@@ -499,10 +499,9 @@ int ras_store_diskerror_event(struct ras_events *ras, struct diskerror_event *ev
 /*
  * Generic code
  */
-
-static int ras_mc_prepare_stmt(struct sqlite3_priv *priv,
-                              sqlite3_stmt **stmt,
-                              const struct db_table_descriptor *db_tab)
+static int __ras_mc_prepare_stmt(struct sqlite3_priv *priv,
+                                sqlite3_stmt **stmt,
+                                const struct db_table_descriptor *db_tab)
 
 {
        int i, rc;
@@ -578,6 +577,92 @@ static int ras_mc_create_table(struct sqlite3_priv *priv,
        return rc;
 }
 
+static int ras_mc_alter_table(struct sqlite3_priv *priv,
+                             sqlite3_stmt **stmt,
+                             const struct db_table_descriptor *db_tab)
+{
+       char sql[1024], *p = sql, *end = sql + sizeof(sql);
+       const struct db_fields *field;
+       int col_count;
+       int i, j, rc, found;
+
+       snprintf(p, end - p, "SELECT * FROM %s", db_tab->name);
+       rc = sqlite3_prepare_v2(priv->db, sql, -1, stmt, NULL);
+       if (rc != SQLITE_OK) {
+               log(TERM, LOG_ERR,
+                   "Failed to query fields from the table %s on %s: error = %d\n",
+                   db_tab->name, SQLITE_RAS_DB, rc);
+               return rc;
+       }
+
+       col_count = sqlite3_column_count(*stmt);
+       for (i = 0; i < db_tab->num_fields; i++) {
+               field = &db_tab->fields[i];
+               found = 0;
+               for (j = 0; j < col_count; j++) {
+                       if (!strcmp(field->name,
+                           sqlite3_column_name(*stmt, j))) {
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       /* add new field */
+                       p += snprintf(p, end - p, "ALTER TABLE %s ADD ",
+                                     db_tab->name);
+                       p += snprintf(p, end - p,
+                                     "%s %s", field->name, field->type);
+#ifdef DEBUG_SQL
+                       log(TERM, LOG_INFO, "SQL: %s\n", sql);
+#endif
+                       rc = sqlite3_exec(priv->db, sql, NULL, NULL, NULL);
+                       if (rc != SQLITE_OK) {
+                               log(TERM, LOG_ERR,
+                                   "Failed to add new field %s to the table %s on %s: error = %d\n",
+                                   field->name, db_tab->name,
+                                   SQLITE_RAS_DB, rc);
+                               return rc;
+                       }
+                       p = sql;
+                       memset(sql, 0, sizeof(sql));
+               }
+       }
+
+       return rc;
+}
+
+static int ras_mc_prepare_stmt(struct sqlite3_priv *priv,
+                              sqlite3_stmt **stmt,
+                              const struct db_table_descriptor *db_tab)
+{
+       int rc;
+
+       rc = __ras_mc_prepare_stmt(priv, stmt, db_tab);
+       if (rc != SQLITE_OK) {
+               log(TERM, LOG_ERR,
+                   "Failed to prepare insert db at table %s (db %s): error = %s\n",
+                   db_tab->name, SQLITE_RAS_DB, sqlite3_errmsg(priv->db));
+
+               log(TERM, LOG_INFO, "Trying to alter db at table %s (db %s)\n",
+                   db_tab->name, SQLITE_RAS_DB);
+
+               rc = ras_mc_alter_table(priv, stmt, db_tab);
+               if (rc != SQLITE_OK && rc != SQLITE_DONE) {
+                       log(TERM, LOG_ERR,
+                           "Failed to alter db at table %s (db %s): error = %s\n",
+                           db_tab->name, SQLITE_RAS_DB,
+                           sqlite3_errmsg(priv->db));
+                       stmt = NULL;
+                       return rc;
+               }
+
+               rc = __ras_mc_prepare_stmt(priv, stmt, db_tab);
+       }
+
+       return rc;
+}
+
 int ras_mc_add_vendor_table(struct ras_events *ras,
                            sqlite3_stmt **stmt,
                            const struct db_table_descriptor *db_tab)