static void query_append_operand (coll_query_t *query, xmms_coll_dag_t *dag, xmmsv_coll_t *coll) { xmmsv_coll_t *op = NULL; gchar *target_name; gchar *target_ns; guint target_nsid; if (!xmmsv_list_get_coll (xmmsv_coll_operands_get (coll), 0, &op)) { /* Ref'd coll not saved as operand, look for it */ if (xmmsv_coll_attribute_get (coll, "reference", &target_name) && xmmsv_coll_attribute_get (coll, "namespace", &target_ns)) { target_nsid = xmms_collection_get_namespace_id (target_ns); op = xmms_collection_get_pointer (dag, target_name, target_nsid); } } /* Append reference operator */ if (op != NULL) { xmms_collection_append_to_query (dag, op, query); /* Cannot find reference, append dummy TRUE */ } else { query_append_string (query, "1"); } }
static void query_append_protect_string (coll_query_t *query, gchar *s) { gchar *preps; if ((preps = sqlite_prepare_string (s)) != NULL) { /* FIXME: Return oom error */ query_append_string (query, preps); g_free (preps); } }
static void query_append_intersect_operand (coll_query_t *query, xmms_coll_dag_t *dag, xmmsv_coll_t *coll) { xmmsv_coll_t *op; xmmsv_t *tmp; if (xmmsv_list_get (xmmsv_coll_operands_get (coll), 0, &tmp)) { xmmsv_get_coll (tmp, &op); if (!operator_is_allmedia (op)) { query_append_string (query, " AND "); xmms_collection_append_to_query (dag, op, query); } } }
static void query_append_intersect_operand (coll_query_t *query, xmms_coll_dag_t *dag, xmmsv_coll_t *coll) { xmmsv_coll_t *op; xmmsv_coll_operand_list_save (coll); xmmsv_coll_operand_list_first (coll); if (xmmsv_coll_operand_list_entry (coll, &op)) { if (!operator_is_allmedia (op)) { query_append_string (query, " AND "); xmms_collection_append_to_query (dag, op, query); } } xmmsv_coll_operand_list_restore (coll); }
/* Append a filtering clause on the field value, depending on the operator type. */ static void query_append_filter (coll_query_t *query, xmmsv_coll_type_t type, gchar *key, gchar *value, gboolean case_sens) { coll_query_alias_t *alias; gboolean optional; gchar *temp; gint i; if (type == XMMS_COLLECTION_TYPE_HAS) { optional = TRUE; } else { optional = FALSE; } alias = query_make_alias (query, key, optional); switch (type) { /* escape strings */ case XMMS_COLLECTION_TYPE_EQUALS: case XMMS_COLLECTION_TYPE_MATCH: if (case_sens) { query_string_append_alias (query->conditions, alias, COLL_QUERY_VALUE_TYPE_STRING); } else { query_append_string (query, "("); query_string_append_alias (query->conditions, alias, COLL_QUERY_VALUE_TYPE_STRING); query_append_string (query, " COLLATE NOCASE)"); } if (type == XMMS_COLLECTION_TYPE_EQUALS) { query_append_string (query, "="); } else { if (case_sens) { query_append_string (query, " GLOB "); } else { query_append_string (query, " LIKE "); } } if (type == XMMS_COLLECTION_TYPE_MATCH && !case_sens) { temp = g_strdup(value); for (i = 0; temp[i]; i++) { switch (temp[i]) { case '*': temp[i] = '%'; break; case '?': temp[i] = '_'; break; default : break; } } query_append_protect_string (query, temp); g_free(temp); } else { query_append_protect_string (query, value); } break; /* do not escape numerical values */ case XMMS_COLLECTION_TYPE_SMALLER: case XMMS_COLLECTION_TYPE_GREATER: query_string_append_alias (query->conditions, alias, COLL_QUERY_VALUE_TYPE_INT); if (type == XMMS_COLLECTION_TYPE_SMALLER) { query_append_string (query, " < "); } else { query_append_string (query, " > "); } query_append_string (query, value); break; case XMMS_COLLECTION_TYPE_HAS: query_string_append_alias (query->conditions, alias, COLL_QUERY_VALUE_TYPE_STRING); query_append_string (query, " is not null"); break; /* Called with invalid type? */ default: g_assert_not_reached (); break; } }
/* Recursively append conditions corresponding to the given collection to the query. */ static void xmms_collection_append_to_query (xmms_coll_dag_t *dag, xmmsv_coll_t *coll, coll_query_t *query) { xmmsv_coll_t *op; xmms_medialib_entry_t entry; gchar *attr1, *attr2, *attr3; gboolean case_sens; xmmsv_list_iter_t *iter; xmmsv_t *tmp; gboolean first; xmmsv_coll_type_t type = xmmsv_coll_get_type (coll); switch (type) { case XMMS_COLLECTION_TYPE_REFERENCE: if (!operator_is_allmedia (coll)) { query_append_operand (query, dag, coll); } else { /* FIXME: Hackish solution to append a ref to All Media */ query_append_string (query, "1"); } break; case XMMS_COLLECTION_TYPE_UNION: case XMMS_COLLECTION_TYPE_INTERSECTION: first = TRUE; query_append_string (query, "("); xmmsv_get_list_iter (xmmsv_coll_operands_get (coll), &iter); for (xmmsv_list_iter_first (iter); xmmsv_list_iter_valid (iter); xmmsv_list_iter_next (iter)) { if (first) { first = FALSE; } else { if (type == XMMS_COLLECTION_TYPE_UNION) query_append_string (query, " OR "); else query_append_string (query, " AND "); } xmmsv_list_iter_entry (iter, &tmp); xmmsv_get_coll (tmp, &op); xmms_collection_append_to_query (dag, op, query); } xmmsv_list_iter_explicit_destroy (iter); query_append_string (query, ")"); break; case XMMS_COLLECTION_TYPE_COMPLEMENT: query_append_string (query, "NOT "); query_append_operand (query, dag, coll); break; case XMMS_COLLECTION_TYPE_HAS: case XMMS_COLLECTION_TYPE_EQUALS: case XMMS_COLLECTION_TYPE_MATCH: case XMMS_COLLECTION_TYPE_SMALLER: case XMMS_COLLECTION_TYPE_GREATER: xmmsv_coll_attribute_get (coll, "field", &attr1); xmmsv_coll_attribute_get (coll, "value", &attr2); xmmsv_coll_attribute_get (coll, "case-sensitive", &attr3); case_sens = (attr3 != NULL && strcmp (attr3, "true") == 0); query_append_string (query, "("); query_append_filter (query, type, attr1, attr2, case_sens); query_append_intersect_operand (query, dag, coll); query_append_string (query, ")"); break; case XMMS_COLLECTION_TYPE_IDLIST: case XMMS_COLLECTION_TYPE_QUEUE: case XMMS_COLLECTION_TYPE_PARTYSHUFFLE: first = TRUE; query_append_string (query, "m0.id IN ("); xmmsv_get_list_iter (xmmsv_coll_idlist_get (coll), &iter); for (xmmsv_list_iter_first (iter); xmmsv_list_iter_valid (iter); xmmsv_list_iter_next (iter)) { if (first) { first = FALSE; } else { query_append_string (query, ","); } xmmsv_list_iter_entry_int (iter, &entry); query_append_int (query, entry); } xmmsv_list_iter_explicit_destroy (iter); query_append_string (query, ")"); break; /* invalid type */ default: XMMS_DBG ("Cannot append invalid collection operator!"); g_assert_not_reached (); break; } }
/* Recursively append conditions corresponding to the given collection to the query. */ static void xmms_collection_append_to_query (xmms_coll_dag_t *dag, xmmsv_coll_t *coll, coll_query_t *query) { gint i; xmmsv_coll_t *op; guint *idlist; gchar *attr1, *attr2, *attr3; gboolean case_sens; xmmsv_coll_type_t type = xmmsv_coll_get_type (coll); switch (type) { case XMMS_COLLECTION_TYPE_REFERENCE: if (!operator_is_allmedia (coll)) { query_append_operand (query, dag, coll); } else { /* FIXME: Hackish solution to append a ref to All Media */ query_append_string (query, "1"); } break; case XMMS_COLLECTION_TYPE_UNION: case XMMS_COLLECTION_TYPE_INTERSECTION: i = 0; query_append_string (query, "("); xmmsv_coll_operand_list_save (coll); xmmsv_coll_operand_list_first (coll); while (xmmsv_coll_operand_list_entry (coll, &op)) { if (i != 0) { if (type == XMMS_COLLECTION_TYPE_UNION) query_append_string (query, " OR "); else query_append_string (query, " AND "); } else { i = 1; } xmms_collection_append_to_query (dag, op, query); xmmsv_coll_operand_list_next (coll); } xmmsv_coll_operand_list_restore (coll); query_append_string (query, ")"); break; case XMMS_COLLECTION_TYPE_COMPLEMENT: query_append_string (query, "NOT "); query_append_operand (query, dag, coll); break; case XMMS_COLLECTION_TYPE_HAS: case XMMS_COLLECTION_TYPE_EQUALS: case XMMS_COLLECTION_TYPE_MATCH: case XMMS_COLLECTION_TYPE_SMALLER: case XMMS_COLLECTION_TYPE_GREATER: xmmsv_coll_attribute_get (coll, "field", &attr1); xmmsv_coll_attribute_get (coll, "value", &attr2); xmmsv_coll_attribute_get (coll, "case-sensitive", &attr3); case_sens = (attr3 != NULL && strcmp (attr3, "true") == 0); query_append_string (query, "("); query_append_filter (query, type, attr1, attr2, case_sens); query_append_intersect_operand (query, dag, coll); query_append_string (query, ")"); break; case XMMS_COLLECTION_TYPE_IDLIST: case XMMS_COLLECTION_TYPE_QUEUE: case XMMS_COLLECTION_TYPE_PARTYSHUFFLE: idlist = xmmsv_coll_get_idlist (coll); query_append_string (query, "m0.id IN ("); for (i = 0; idlist[i] != 0; ++i) { if (i != 0) { query_append_string (query, ","); } query_append_uint (query, idlist[i]); } query_append_string (query, ")"); break; /* invalid type */ default: XMMS_DBG ("Cannot append invalid collection operator!"); g_assert_not_reached (); break; } }