SIG_CREATE_FIELDS, /**< Fields for create query */
SIG_INSERT_FIELDS, /**< Fields for insert query */
SIG_INSERT_VALUES, /**< Values for insert query */
+ SIG_LIKE_PATTERN, /**< Pattern for sql LIKE operator */
+ SIG_WHERE_QUERY, /**< WHERE operators for query */
};
+static const char *get_query_op(const char *key)
+{
+ int i;
+ static const struct {
+ const char *k;
+ const char *v;
+ } map[] = {
+ {"$not", "!="},
+ {"$lt", "<"},
+ {"$lte", "<="},
+ {"$gte", ">"},
+ {"$gt", ">="},
+ {NULL, NULL},
+ };
+
+ for (i = 0; map[i].k; ++i)
+ if (strcmp(map[i].k, key) == 0)
+ return map[i].v;
+
+ return NULL;
+}
+
static int _get_object_signature(struct faultd_object *obj, char *buffer, size_t size, int offset, int type, const char *key_prefix)
{
struct faultd_object *child;
int ret = 0;
int noff = offset;
char *prefix = NULL;
+ const char *op;
- if (obj->key && strcmp(obj->key, ID_KEY) == 0
- && type != SIG_INSERT_VALUES && type != SIG_INSERT_FIELDS)
+ if (obj->key && (strcmp(obj->key, ID_KEY) == 0
+ && type != SIG_INSERT_VALUES && type != SIG_INSERT_FIELDS
+ || ((type != SIG_WHERE_QUERY && obj->key[0] == '$'))))
return 0;
if (obj->type == TYPE_OBJECT) {
ret = asprintf(&prefix, "%s%s.", (key_prefix ? key_prefix : ""), obj->key);
else
prefix = strdup(key_prefix);
+
if (ret < 0 || !prefix)
return -ENOMEM;
list_for_each_entry(child, &obj->val.children, node) {
+ if (type == SIG_LIKE_PATTERN)
+ buffer[noff++] = '%';
+
ret = _get_object_signature(child, buffer, size, noff, type, prefix);
if (ret < 0)
goto out;
switch (type) {
case SIG_KEY:
+ case SIG_LIKE_PATTERN:
if (obj->key && size < offset + strlen(obj->key) + 3)
return -ENOMEM;
case SIG_INSERT_VALUES:
ret = snprintf(buffer + offset, size - offset, "?,");
break;
+ case SIG_WHERE_QUERY:
+ op = NULL;
+ if (obj->key && obj->key[0] == '$')
+ op = get_query_op(obj->key);
+
+ ret = snprintf(buffer + offset, size - offset, "%s `%.*s%s` %s ? ",
+ (offset == 0 ? "WHERE" : "AND"),
+ strlen(key_prefix) - (op ? 1 : 0),
+ key_prefix, op ? "" : obj->key,
+ op ? op : "=");
+ break;
}
if (ret < 0 || ret >= (int)size - offset)
static int sqlite_load(struct faultd_database_adapter *adapter, struct faultd_object *query,
struct faultd_object *hints, struct faultd_object *result, uint32_t *nr)
{
- return 0;
+ sqlite3_stmt *sql_query, *subquery;
+ struct sqlite_adapter *da = to_sqlite_adapter(adapter);
+ int ret;
+ const char *name, *signature;
+ char qsignature[BUFSIZE];
+ char query_str[BUFSIZE];
+ uint32_t n = 0;
+ int table_id;
+
+ ret = get_object_signature(query, qsignature, BUFSIZE, SIG_LIKE_PATTERN);
+ if (ret < 0) {
+ log_error_errno(ret, "Could not create database query: %m");
+ return ret;
+ }
+
+ ret = snprintf(query_str, BUFSIZE, "SELECT ('" OBJ_TABLE_PREFIX "'||id), signature, id FROM " META_TABLE
+ " WHERE signature LIKE '%s%%';", qsignature);
+ if (ret < 0 || ret >= BUFSIZE)
+ return -ENOMEM;
+
+ ret = sqlite3_prepare_v2(da->db, query_str, -1, &sql_query, NULL);
+ if (ret != SQLITE_OK) {
+ log_error("SQL Error: %s", sqlite3_errmsg(da->db));
+ return ret;
+ }
+
+ log_debug("query: %s", sqlite3_expanded_sql(sql_query));
+
+ ret = get_object_signature(query, qsignature, BUFSIZE, SIG_WHERE_QUERY);
+ if (ret < 0) {
+ log_error_errno(ret, "Could not create database query: %m");
+ return ret;
+ }
+
+ while ((ret = sqlite3_step(sql_query)) == SQLITE_ROW) {
+ name = (const char *)sqlite3_column_text(sql_query, 0);
+ signature = (const char *)sqlite3_column_text(sql_query, 1);
+ table_id = sqlite3_column_int(sql_query, 2);
+
+ ret = snprintf(query_str, BUFSIZE, "SELECT * FROM %s %s;", name, qsignature);
+ if (ret < 0 || ret >= BUFSIZE)
+ return ret;
+
+ log_debug("query: %s", query_str);
+ ret = sqlite3_prepare_v2(da->db, query_str, -1, &subquery, NULL);
+ if (ret != SQLITE_OK) {
+ log_error("SQL Error: %s", sqlite3_errmsg(da->db));
+ return ret;
+ }
+
+ ret = bind_values(query, subquery, 1);
+ if (ret < 0) {
+ log_error_errno(ret, "could not bind values to query");
+ }
+
+ log_debug("query: %s", sqlite3_expanded_sql(subquery));
+
+ while ((ret = sqlite3_step(subquery)) == SQLITE_ROW) {
+ int idx = 0;
+ struct faultd_object *part_result;
+ char key[11]; /* strlen(itoa(UINT_MAX, key, 10)) => 10 */
+
+ /* FIXME do count instead of select when result is NULL*/
+ if (!result) {
+ n++;
+ continue;
+ }
+
+ log_debug("fetched row %u", n);
+ ret = snprintf(key, sizeof(key), "%u", n);
+ if (ret < 0 || ret >= sizeof(key))
+ return -ENOMEM;
+
+ ret = faultd_object_new(&part_result);
+ if (ret < 0) {
+ log_error_errno(ret, "could not create faultd object");
+ goto finish;
+ }
+
+ ret = build_faultd_object(subquery, &idx, signature, 1, part_result, table_id);
+ if (ret < 0) {
+ log_error_errno(ret, "could not build faultd_object: %m");
+ goto finish;
+ }
+
+ faultd_object_append_object(result, key, part_result);
+ faultd_object_unref(part_result);
+ n++;
+ }
+ }
+
+ ret = 0;
+
+finish:
+ if (ret == 0 && nr != NULL)
+ *nr = n;
+
+ return ret;
}
static int sqlite_get_well_known_oid(const char *name, faultd_oid_t *oid)