|
|
|
|
@ -872,199 +872,6 @@ typedef struct
|
|
|
|
|
gboolean has_been_run;
|
|
|
|
|
} split_query_info_t;
|
|
|
|
|
|
|
|
|
|
#define TX_GUID_CHECK 0
|
|
|
|
|
|
|
|
|
|
G_GNUC_UNUSED static gpointer
|
|
|
|
|
compile_split_query (GncSqlBackend* sql_be, QofQuery* query)
|
|
|
|
|
{
|
|
|
|
|
split_query_info_t* query_info = NULL;
|
|
|
|
|
gchar* query_sql;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (sql_be != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (query != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
query_info = static_cast<decltype (query_info)> (
|
|
|
|
|
g_malloc (sizeof (split_query_info_t)));
|
|
|
|
|
g_assert (query_info != NULL);
|
|
|
|
|
query_info->has_been_run = FALSE;
|
|
|
|
|
|
|
|
|
|
if (qof_query_has_terms (query))
|
|
|
|
|
{
|
|
|
|
|
GList* orterms = qof_query_get_terms (query);
|
|
|
|
|
GList* orTerm;
|
|
|
|
|
std::stringstream sql;
|
|
|
|
|
gboolean need_OR = FALSE;
|
|
|
|
|
|
|
|
|
|
for (orTerm = orterms; orTerm != NULL; orTerm = orTerm->next)
|
|
|
|
|
{
|
|
|
|
|
GList* andterms = (GList*)orTerm->data;
|
|
|
|
|
GList* andTerm;
|
|
|
|
|
gboolean need_AND = FALSE;
|
|
|
|
|
#if TX_GUID_CHECK
|
|
|
|
|
gboolean has_tx_guid_check = FALSE;
|
|
|
|
|
#endif
|
|
|
|
|
if (need_OR)
|
|
|
|
|
{
|
|
|
|
|
sql << " OR ";
|
|
|
|
|
}
|
|
|
|
|
sql << "(";
|
|
|
|
|
for (andTerm = andterms; andTerm != NULL; andTerm = andTerm->next)
|
|
|
|
|
{
|
|
|
|
|
QofQueryTerm* term;
|
|
|
|
|
GSList* paramPath;
|
|
|
|
|
gboolean unknownPath = FALSE;
|
|
|
|
|
|
|
|
|
|
term = (QofQueryTerm*)andTerm->data;
|
|
|
|
|
paramPath = qof_query_term_get_param_path (term);
|
|
|
|
|
const char* path = static_cast<decltype (path)> (paramPath->data);
|
|
|
|
|
const char* next_path =
|
|
|
|
|
static_cast<decltype (next_path)> (paramPath->next->data);
|
|
|
|
|
if (strcmp (path, QOF_PARAM_BOOK) == 0) continue;
|
|
|
|
|
|
|
|
|
|
#if SIMPLE_QUERY_COMPILATION
|
|
|
|
|
if (strcmp (path, SPLIT_ACCOUNT) != 0 ||
|
|
|
|
|
strcmp (next_path, QOF_PARAM_GUID) != 0) continue;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (need_AND) sql<< " AND ";
|
|
|
|
|
|
|
|
|
|
if (strcmp (path, SPLIT_ACCOUNT) == 0 &&
|
|
|
|
|
strcmp (next_path, QOF_PARAM_GUID) == 0)
|
|
|
|
|
{
|
|
|
|
|
convert_query_term_to_sql (sql_be, "s.account_guid", term,
|
|
|
|
|
sql);
|
|
|
|
|
#if SIMPLE_QUERY_COMPILATION
|
|
|
|
|
goto done_compiling_query;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (strcmp (path, SPLIT_RECONCILE) == 0)
|
|
|
|
|
{
|
|
|
|
|
convert_query_term_to_sql (sql_be, "s.reconcile_state",
|
|
|
|
|
term, sql);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (strcmp (path, SPLIT_TRANS) == 0)
|
|
|
|
|
{
|
|
|
|
|
#if TX_GUID_CHECK
|
|
|
|
|
if (!has_tx_guid_check)
|
|
|
|
|
{
|
|
|
|
|
sql << "(splits.tx_guid = transactions.guid) AND ");
|
|
|
|
|
has_tx_guid_check = TRUE;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (strcmp (next_path, TRANS_DATE_POSTED) == 0)
|
|
|
|
|
{
|
|
|
|
|
convert_query_term_to_sql (sql_be, "t.post_date", term,
|
|
|
|
|
sql);
|
|
|
|
|
}
|
|
|
|
|
else if (strcmp (next_path, TRANS_DESCRIPTION) == 0)
|
|
|
|
|
{
|
|
|
|
|
convert_query_term_to_sql (sql_be, "t.description",
|
|
|
|
|
term, sql);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unknownPath = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (strcmp (path, SPLIT_VALUE) == 0)
|
|
|
|
|
{
|
|
|
|
|
convert_query_term_to_sql (sql_be,
|
|
|
|
|
"s.value_num/s.value_denom",
|
|
|
|
|
term, sql);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unknownPath = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unknownPath)
|
|
|
|
|
{
|
|
|
|
|
std::stringstream name;
|
|
|
|
|
name << static_cast<char*>(paramPath->data);
|
|
|
|
|
for (;paramPath->next != NULL; paramPath = paramPath->next)
|
|
|
|
|
{
|
|
|
|
|
next_path =
|
|
|
|
|
static_cast<decltype (next_path)>(paramPath->next->data);
|
|
|
|
|
name << "." << next_path;
|
|
|
|
|
}
|
|
|
|
|
PERR ("Unknown SPLIT query field: %s\n",
|
|
|
|
|
name.str().c_str());
|
|
|
|
|
}
|
|
|
|
|
need_AND = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If the last char in the string is a '(', then for some reason, there were
|
|
|
|
|
no terms added to the SQL. If so, remove it and ignore the OR term. */
|
|
|
|
|
if (!sql.str().empty() && sql.str().back() == '(')
|
|
|
|
|
{
|
|
|
|
|
sql.str().erase(sql.str().back());
|
|
|
|
|
need_OR = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sql << ")";
|
|
|
|
|
need_OR = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if SIMPLE_QUERY_COMPILATION
|
|
|
|
|
done_compiling_query:
|
|
|
|
|
#endif
|
|
|
|
|
if (!sql.str().empty())
|
|
|
|
|
{
|
|
|
|
|
#if SIMPLE_QUERY_COMPILATION
|
|
|
|
|
sql<< ")";
|
|
|
|
|
#endif
|
|
|
|
|
query_sql = g_strdup_printf (
|
|
|
|
|
"SELECT DISTINCT t.* FROM %s AS t, %s AS s WHERE s.tx_guid=t.guid AND %s",
|
|
|
|
|
TRANSACTION_TABLE, SPLIT_TABLE, sql.str().c_str());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
|
|
|
|
|
}
|
|
|
|
|
query_info->stmt = sql_be->create_statement_from_sql(query_sql);
|
|
|
|
|
g_free (query_sql);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
query_sql = g_strdup_printf ("SELECT * FROM %s", TRANSACTION_TABLE);
|
|
|
|
|
query_info->stmt = sql_be->create_statement_from_sql(query_sql);
|
|
|
|
|
g_free (query_sql);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return query_info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_GNUC_UNUSED static void
|
|
|
|
|
run_split_query (GncSqlBackend* sql_be, gpointer pQuery)
|
|
|
|
|
{
|
|
|
|
|
split_query_info_t* query_info = (split_query_info_t*)pQuery;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (sql_be != NULL);
|
|
|
|
|
g_return_if_fail (pQuery != NULL);
|
|
|
|
|
|
|
|
|
|
if (!query_info->has_been_run)
|
|
|
|
|
{
|
|
|
|
|
query_transactions (sql_be, query_info->stmt);
|
|
|
|
|
query_info->has_been_run = TRUE;
|
|
|
|
|
query_info->stmt = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_GNUC_UNUSED static void
|
|
|
|
|
free_split_query (GncSqlBackend* sql_be, gpointer pQuery)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (sql_be != NULL);
|
|
|
|
|
g_return_if_fail (pQuery != NULL);
|
|
|
|
|
|
|
|
|
|
g_free (pQuery);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
@ -1118,22 +925,6 @@ static const EntryVec acct_balances_col_table
|
|
|
|
|
(QofSetterFunc)set_acct_bal_balance),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
G_GNUC_UNUSED static single_acct_balance_t*
|
|
|
|
|
load_single_acct_balances (const GncSqlBackend* sql_be, GncSqlRow& row)
|
|
|
|
|
{
|
|
|
|
|
single_acct_balance_t* bal = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (sql_be != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
bal = static_cast<decltype (bal)> (g_malloc (sizeof (single_acct_balance_t)));
|
|
|
|
|
g_assert (bal != NULL);
|
|
|
|
|
|
|
|
|
|
bal->sql_be = sql_be;
|
|
|
|
|
gnc_sql_load_object (sql_be, row, NULL, bal, acct_balances_col_table);
|
|
|
|
|
|
|
|
|
|
return bal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
|
template<> void
|
|
|
|
|
GncSqlColumnTableEntryImpl<CT_TXREF>::load (const GncSqlBackend* sql_be,
|
|
|
|
|
|