コード例 #1
0
ファイル: gnc-tax-table-sql.c プロジェクト: cstim/gnucash-svn
static void
load_taxtable_entries( GncSqlBackend* be, GncTaxTable* tt )
{
    GncSqlResult* result;
    gchar guid_buf[GUID_ENCODING_LENGTH+1];
    GValue value;
    gchar* buf;
    GncSqlStatement* stmt;
    GError* error = NULL;

    g_return_if_fail( be != NULL );
    g_return_if_fail( tt != NULL );

    guid_to_string_buff( qof_instance_get_guid( QOF_INSTANCE(tt) ), guid_buf );
    memset( &value, 0, sizeof( GValue ) );
    g_value_init( &value, G_TYPE_STRING );
    g_value_set_string( &value, guid_buf );
    buf = g_strdup_printf( "SELECT * FROM %s WHERE taxtable='%s'", TTENTRIES_TABLE_NAME, guid_buf );
    stmt = gnc_sql_connection_create_statement_from_sql( be->conn, buf );
    g_free( buf );
    result = gnc_sql_execute_select_statement( be, stmt );
    gnc_sql_statement_dispose( stmt );
    if ( result != NULL )
    {
        GncSqlRow* row;

        row = gnc_sql_result_get_first_row( result );
        while ( row != NULL )
        {
            load_single_ttentry( be, row, tt );
            row = gnc_sql_result_get_next_row( result );
        }
        gnc_sql_result_dispose( result );
    }
}
コード例 #2
0
ファイル: gnc-employee-sql.cpp プロジェクト: CAARNICL/gnucash
static void
load_all_employees (GncSqlBackend* be)
{
    GncSqlStatement* stmt;
    GncSqlResult* result;

    g_return_if_fail (be != NULL);

    stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
    result = gnc_sql_execute_select_statement (be, stmt);
    gnc_sql_statement_dispose (stmt);
    if (result != NULL)
    {
        GncSqlRow* row;
        GList* list = NULL;

        row = gnc_sql_result_get_first_row (result);
        while (row != NULL)
        {
            GncEmployee* pEmployee = load_single_employee (be, row);
            if (pEmployee != NULL)
            {
                list = g_list_append (list, pEmployee);
            }
            row = gnc_sql_result_get_next_row (result);
        }
        gnc_sql_result_dispose (result);

        if (list != NULL)
        {
            gnc_sql_slots_load_for_list (be, list);
            g_list_free (list);
        }
    }
}
コード例 #3
0
ファイル: gnc-recurrence-sql.c プロジェクト: 573/gnucash
/*@ null @*/ GList*
gnc_sql_recurrence_load_list( GncSqlBackend* be, const GncGUID* guid )
{
    GncSqlResult* result;
    GList* list = NULL;

    g_return_val_if_fail( be != NULL, NULL );
    g_return_val_if_fail( guid != NULL, NULL );

    result = gnc_sql_set_recurrences_from_db( be, guid );
    if ( result != NULL )
    {
        GncSqlRow* row = gnc_sql_result_get_first_row( result );

        while ( row != NULL )
        {
            Recurrence* pRecurrence = g_new0( Recurrence, 1 );
            g_assert( pRecurrence != NULL );
            load_recurrence( be, row, pRecurrence );
            list = g_list_append( list, pRecurrence );
            row = gnc_sql_result_get_next_row( result );
        }
        gnc_sql_result_dispose( result );
    }

    return list;
}
コード例 #4
0
static void
load_all_lots( GncSqlBackend* be )
{
    GncSqlStatement* stmt;
    GncSqlResult* result;

    g_return_if_fail( be != NULL );

    stmt = gnc_sql_create_select_statement( be, TABLE_NAME );
    if ( stmt != NULL )
    {
        result = gnc_sql_execute_select_statement( be, stmt );
        gnc_sql_statement_dispose( stmt );
        if ( result != NULL )
        {
            GncSqlRow* row = gnc_sql_result_get_first_row( result );
            gchar* sql;

            while ( row != NULL )
            {
                load_single_lot( be, row );
                row = gnc_sql_result_get_next_row( result );
            }
            gnc_sql_result_dispose( result );

            sql = g_strdup_printf( "SELECT DISTINCT guid FROM %s", TABLE_NAME );
            gnc_sql_slots_load_for_sql_subquery( be, sql, (BookLookupFn)gnc_lot_lookup );
            g_free( sql );
        }
    }
}
コード例 #5
0
ファイル: gnc-slots-sql.c プロジェクト: nishmu/gnucash
void
gnc_sql_slots_load_for_list( GncSqlBackend* be, GList* list )
{
    QofCollection* coll;
    GncSqlStatement* stmt;
    GString* sql;
    GncSqlResult* result;
    gboolean single_item;

    g_return_if_fail( be != NULL );

    // Ignore empty list
    if ( list == NULL ) return;

    coll = qof_instance_get_collection( QOF_INSTANCE(list->data) );

    // Create the query for all slots for all items on the list
    sql = g_string_sized_new( 40 + (GUID_ENCODING_LENGTH + 3) * g_list_length( list ) );
    g_string_append_printf( sql, "SELECT * FROM %s WHERE %s ", TABLE_NAME, obj_guid_col_table[0].col_name );
    if ( g_list_length( list ) != 1 )
    {
        (void)g_string_append( sql, "IN (" );
        single_item = FALSE;
    }
    else
    {
        (void)g_string_append( sql, "= " );
        single_item = TRUE;
    }
    (void)gnc_sql_append_guid_list_to_sql( sql, list, G_MAXUINT );
    if ( !single_item )
    {
        (void)g_string_append( sql, ")" );
    }

    // Execute the query and load the slots
    stmt = gnc_sql_create_statement_from_sql( be, sql->str );
    if ( stmt == NULL )
    {
        PERR( "stmt == NULL, SQL = '%s'\n", sql->str );
        (void)g_string_free( sql, TRUE );
        return;
    }
    (void)g_string_free( sql, TRUE );
    result = gnc_sql_execute_select_statement( be, stmt );
    gnc_sql_statement_dispose( stmt );
    if ( result != NULL )
    {
        GncSqlRow* row = gnc_sql_result_get_first_row( result );

        while ( row != NULL )
        {
            load_slot_for_list_item( be, row, coll );
            row = gnc_sql_result_get_next_row( result );
        }
        gnc_sql_result_dispose( result );
    }
}
コード例 #6
0
ファイル: gnc-slots-sql.c プロジェクト: nishmu/gnucash
gboolean
gnc_sql_slots_delete( GncSqlBackend* be, const GncGUID* guid )
{
    gchar* buf;
    GncSqlResult* result;
    gchar guid_buf[GUID_ENCODING_LENGTH + 1];
    GncSqlStatement* stmt;
    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, g_string_new('\0') };

    g_return_val_if_fail( be != NULL, FALSE );
    g_return_val_if_fail( guid != NULL, FALSE );

    (void)guid_to_string_buff( guid, guid_buf );

    buf = g_strdup_printf( "SELECT * FROM %s WHERE obj_guid='%s' and slot_type in ('%d', '%d') and not guid_val is null",
                           TABLE_NAME, guid_buf, KVP_TYPE_FRAME, KVP_TYPE_GLIST );
    stmt = gnc_sql_create_statement_from_sql( be, buf );
    g_free( buf );
    if ( stmt != NULL )
    {
        result = gnc_sql_execute_select_statement( be, stmt );
        gnc_sql_statement_dispose( stmt );
        if ( result != NULL )
        {
            GncSqlRow* row = gnc_sql_result_get_first_row( result );

            while ( row != NULL )
            {
                GncSqlColumnTableEntry table_row = col_table[guid_val_col];
                GncGUID child_guid;
                const GValue* val =
                    gnc_sql_row_get_value_at_col_name( row, table_row.col_name);
                if ( val == NULL )
                    continue;

                (void)string_to_guid( g_value_get_string( val ), &child_guid );
                gnc_sql_slots_delete( be, &child_guid );
                row = gnc_sql_result_get_next_row( result );
            }
            gnc_sql_result_dispose( result );
        }
    }

    slot_info.be = be;
    slot_info.guid = guid;
    slot_info.is_ok = TRUE;
    slot_info.is_ok = gnc_sql_do_db_operation( be, OP_DB_DELETE, TABLE_NAME,
                      TABLE_NAME, &slot_info, obj_guid_col_table );

    return slot_info.is_ok;
}
コード例 #7
0
ファイル: gnc-tax-table-sql.c プロジェクト: cstim/gnucash-svn
static void
load_all_taxtables( GncSqlBackend* be )
{
    GncSqlStatement* stmt;
    GncSqlResult* result;

    g_return_if_fail( be != NULL );

    /* First time, create the query */
    stmt = gnc_sql_create_select_statement( be, TT_TABLE_NAME );
    result = gnc_sql_execute_select_statement( be, stmt );
    gnc_sql_statement_dispose( stmt );
    if ( result != NULL )
    {
        GncSqlRow* row;
        GList* tt_needing_parents = NULL;

        row = gnc_sql_result_get_first_row( result );
        while ( row != NULL )
        {
            load_single_taxtable( be, row, &tt_needing_parents );
            row = gnc_sql_result_get_next_row( result );
        }
        gnc_sql_result_dispose( result );

        /* While there are items on the list of taxtables needing parents,
           try to see if the parent has now been loaded.  Theory says that if
           items are removed from the front and added to the back if the
           parent is still not available, then eventually, the list will
           shrink to size 0. */
        if ( tt_needing_parents != NULL )
        {
            gboolean progress_made = TRUE;
            GncTaxTable* root;
            Account* pParent;
            GList* elem;

            while ( progress_made )
            {
                progress_made = FALSE;
                for ( elem = tt_needing_parents; elem != NULL; elem = g_list_next( elem ) )
                {
                    taxtable_parent_guid_struct* s = (taxtable_parent_guid_struct*)elem->data;
                    tt_set_parent( s->tt, &s->guid );
                    tt_needing_parents = g_list_delete_link( tt_needing_parents, elem );
                    progress_made = TRUE;
                }
            }
        }
    }
}
コード例 #8
0
static void
load_splits_for_tx_list (GncSqlBackend* be, GList* list)
{
    GString* sql;
    GncSqlResult* result;

    g_return_if_fail (be != NULL);

    if (list == NULL) return;

    sql = g_string_sized_new (40 + (GUID_ENCODING_LENGTH + 3) * g_list_length (
                                  list));
    g_string_append_printf (sql, "SELECT * FROM %s WHERE %s IN (", SPLIT_TABLE,
                            tx_guid_col_table[0].col_name);
    (void)gnc_sql_append_guid_list_to_sql (sql, list, G_MAXUINT);
    (void)g_string_append (sql, ")");

    // Execute the query and load the splits
    result = gnc_sql_execute_select_sql (be, sql->str);
    if (result != NULL)
    {
        GList* split_list = NULL;
        GncSqlRow* row;

        row = gnc_sql_result_get_first_row (result);
        while (row != NULL)
        {
            Split* s;
            s = load_single_split (be, row);
            if (s != NULL)
            {
                split_list = g_list_prepend (split_list, s);
            }
            row = gnc_sql_result_get_next_row (result);
        }

        if (split_list != NULL)
        {
            gnc_sql_slots_load_for_list (be, split_list);
            g_list_free (split_list);
        }

        gnc_sql_result_dispose (result);
    }
    (void)g_string_free (sql, TRUE);
}
コード例 #9
0
ファイル: gnc-price-sql.cpp プロジェクト: CAARNICL/gnucash
static void
load_all_prices (GncSqlBackend* be)
{
    GncSqlStatement* stmt;
    GncSqlResult* result;
    QofBook* pBook;
    GNCPriceDB* pPriceDB;

    g_return_if_fail (be != NULL);

    pBook = be->book;
    pPriceDB = gnc_pricedb_get_db (pBook);
    stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
    if (stmt != NULL)
    {
        result = gnc_sql_execute_select_statement (be, stmt);
        gnc_sql_statement_dispose (stmt);
        if (result != NULL)
        {
            GNCPrice* pPrice;
            GncSqlRow* row = gnc_sql_result_get_first_row (result);
            gchar* sql;

            gnc_pricedb_set_bulk_update (pPriceDB, TRUE);
            while (row != NULL)
            {
                pPrice = load_single_price (be, row);

                if (pPrice != NULL)
                {
                    (void)gnc_pricedb_add_price (pPriceDB, pPrice);
                    gnc_price_unref (pPrice);
                }
                row = gnc_sql_result_get_next_row (result);
            }
            gnc_sql_result_dispose (result);
            gnc_pricedb_set_bulk_update (pPriceDB, FALSE);

            sql = g_strdup_printf ("SELECT DISTINCT guid FROM %s", TABLE_NAME);
            gnc_sql_slots_load_for_sql_subquery (be, sql, (BookLookupFn)gnc_price_lookup);
            g_free (sql);
        }
    }
}
コード例 #10
0
static void
load_all_commodities( GncSqlBackend* be )
{
    GncSqlStatement* stmt;
    GncSqlResult* result;
    gnc_commodity_table* pTable;

    pTable = gnc_commodity_table_get_table( be->book );
    stmt = gnc_sql_create_select_statement( be, COMMODITIES_TABLE );
    if ( stmt == NULL ) return;
    result = gnc_sql_execute_select_statement( be, stmt );
    gnc_sql_statement_dispose( stmt );
    if ( result != NULL )
    {
        gnc_commodity* pCommodity;
        GncSqlRow* row = gnc_sql_result_get_first_row( result );
        gchar* sql;

        while ( row != NULL )
        {
            pCommodity = load_single_commodity( be, row );

            if ( pCommodity != NULL )
            {
                GncGUID guid;

                guid = *qof_instance_get_guid( QOF_INSTANCE(pCommodity) );
                pCommodity = gnc_commodity_table_insert( pTable, pCommodity );
                qof_instance_set_guid( QOF_INSTANCE(pCommodity), &guid );
            }
            row = gnc_sql_result_get_next_row( result );
        }
        gnc_sql_result_dispose( result );

        sql = g_strdup_printf( "SELECT DISTINCT guid FROM %s", COMMODITIES_TABLE );
        gnc_sql_slots_load_for_sql_subquery( be, sql,
                                             (BookLookupFn)gnc_commodity_find_commodity_by_guid );
        g_free( sql );
    }
}
コード例 #11
0
ファイル: gnc-slots-sql.c プロジェクト: nishmu/gnucash
/**
 * gnc_sql_slots_load_for_sql_subquery - Loads slots for all objects whose guid is
 * supplied by a subquery.  The subquery should be of the form "SELECT DISTINCT guid FROM ...".
 * This is faster than loading for one object at a time because fewer SQL queries * are used.
 *
 * @param be SQL backend
 * @param subquery Subquery SQL string
 * @param lookup_fn Lookup function
 */
void gnc_sql_slots_load_for_sql_subquery( GncSqlBackend* be, const gchar* subquery,
        BookLookupFn lookup_fn )
{
    gchar* sql;
    GncSqlStatement* stmt;
    GncSqlResult* result;

    g_return_if_fail( be != NULL );

    // Ignore empty subquery
    if ( subquery == NULL ) return;

    sql = g_strdup_printf( "SELECT * FROM %s WHERE %s IN (%s)",
                           TABLE_NAME, obj_guid_col_table[0].col_name,
                           subquery );

    // Execute the query and load the slots
    stmt = gnc_sql_create_statement_from_sql( be, sql );
    if ( stmt == NULL )
    {
        PERR( "stmt == NULL, SQL = '%s'\n", sql );
        g_free( sql );
        return;
    }
    g_free( sql );
    result = gnc_sql_execute_select_statement( be, stmt );
    gnc_sql_statement_dispose( stmt );
    if ( result != NULL )
    {
        GncSqlRow* row = gnc_sql_result_get_first_row( result );

        while ( row != NULL )
        {
            load_slot_for_book_object( be, row, lookup_fn );
            row = gnc_sql_result_get_next_row( result );
        }
        gnc_sql_result_dispose( result );
    }
}
コード例 #12
0
ファイル: gnc-slots-sql.c プロジェクト: nishmu/gnucash
static void
slots_load_info ( slot_info_t *pInfo )
{
    gchar* buf;
    GncSqlResult* result;
    gchar guid_buf[GUID_ENCODING_LENGTH + 1];
    GncSqlStatement* stmt;

    g_return_if_fail( pInfo != NULL );
    g_return_if_fail( pInfo->be != NULL );
    g_return_if_fail( pInfo->guid != NULL );
    g_return_if_fail( pInfo->pKvpFrame != NULL );

    (void)guid_to_string_buff( pInfo->guid, guid_buf );

    buf = g_strdup_printf( "SELECT * FROM %s WHERE obj_guid='%s'",
                           TABLE_NAME, guid_buf );
    stmt = gnc_sql_create_statement_from_sql( pInfo->be, buf );
    g_free( buf );
    if ( stmt != NULL )
    {
        result = gnc_sql_execute_select_statement( pInfo->be, stmt );
        gnc_sql_statement_dispose( stmt );
        if ( result != NULL )
        {
            GncSqlRow* row = gnc_sql_result_get_first_row( result );

            while ( row != NULL )
            {
                load_slot( pInfo, row );
                row = gnc_sql_result_get_next_row( result );
            }
            gnc_sql_result_dispose( result );
        }
    }
}
コード例 #13
0
static void
load_all_billterms (GncSqlBackend* be)
{
    GncSqlStatement* stmt;
    GncSqlResult* result;

    g_return_if_fail (be != NULL);

    stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
    result = gnc_sql_execute_select_statement (be, stmt);
    gnc_sql_statement_dispose (stmt);
    if (result != NULL)
    {
        GncSqlRow* row;
        GList* list = NULL;
        GList* l_billterms_needing_parents = NULL;

        row = gnc_sql_result_get_first_row (result);
        while (row != NULL)
        {
            GncBillTerm* pBillTerm = load_single_billterm (be, row,
                                                           &l_billterms_needing_parents);
            if (pBillTerm != NULL)
            {
                list = g_list_append (list, pBillTerm);
            }
            row = gnc_sql_result_get_next_row (result);
        }
        gnc_sql_result_dispose (result);

        if (list != NULL)
        {
            gnc_sql_slots_load_for_list (be, list);
            g_list_free (list);
        }

        /* While there are items on the list of billterms needing parents,
           try to see if the parent has now been loaded.  Theory says that if
           items are removed from the front and added to the back if the
           parent is still not available, then eventually, the list will
           shrink to size 0. */
        if (l_billterms_needing_parents != NULL)
        {
            gboolean progress_made = TRUE;
            GList* elem;

            while (progress_made)
            {
                progress_made = FALSE;
                for (elem = l_billterms_needing_parents; elem != NULL;
                     elem = g_list_next (elem))
                {
                    billterm_parent_guid_struct* s = (billterm_parent_guid_struct*)elem->data;
                    bt_set_parent (s->billterm, &s->guid);
                    l_billterms_needing_parents = g_list_delete_link (l_billterms_needing_parents,
                                                                      elem);
                    progress_made = TRUE;
                }
            }
        }
    }
}
コード例 #14
0
/**
 * Executes a transaction query statement and loads the transactions and all
 * of the splits.
 *
 * @param be SQL backend
 * @param stmt SQL statement
 */
static void
query_transactions( GncSqlBackend* be, GncSqlStatement* stmt )
{
    GncSqlResult* result;

    g_return_if_fail( be != NULL );
    g_return_if_fail( stmt != NULL );

    result = gnc_sql_execute_select_statement( be, stmt );
    if ( result != NULL )
    {
        GList* tx_list = NULL;
        GList* node;
        GncSqlRow* row;
        Transaction* tx;
#if LOAD_TRANSACTIONS_AS_NEEDED
        GSList* bal_list = NULL;
        GSList* nextbal;
        Account* root = gnc_book_get_root_account( be->book );

        qof_event_suspend();
        xaccAccountBeginEdit( root );

        // Save the start/ending balances (balance, cleared and reconciled) for
        // every account.
        gnc_account_foreach_descendant( gnc_book_get_root_account( be->primary_book ),
                                        save_account_balances,
                                        &bal_list );
#endif

        // Load the transactions
        row = gnc_sql_result_get_first_row( result );
        while ( row != NULL )
        {
            tx = load_single_tx( be, row );
            if ( tx != NULL )
            {
                tx_list = g_list_prepend( tx_list, tx );
            }
            row = gnc_sql_result_get_next_row( result );
        }
        gnc_sql_result_dispose( result );

        // Load all splits and slots for the transactions
        if ( tx_list != NULL )
        {
            gnc_sql_slots_load_for_list( be, tx_list );
            load_splits_for_tx_list( be, tx_list );
        }

        // Commit all of the transactions
        for ( node = tx_list; node != NULL; node = node->next )
        {
            Transaction* pTx = GNC_TRANSACTION(node->data);
            xaccTransCommitEdit( pTx );
        }
        g_list_free( tx_list );

#if LOAD_TRANSACTIONS_AS_NEEDED
        // Update the account balances based on the loaded splits.  If the end
        // balance has changed, update the start balance so that the end
        // balance is the same as it was before the splits were loaded.
        // Repeat for cleared and reconciled balances.
        for ( nextbal = bal_list; nextbal != NULL; nextbal = nextbal->next )
        {
            full_acct_balances_t* balns = (full_acct_balances_t*)nextbal->data;
            gnc_numeric* pnew_end_bal;
            gnc_numeric* pnew_end_c_bal;
            gnc_numeric* pnew_end_r_bal;
            gnc_numeric adj;

            g_object_get( balns->acc,
                          "end-balance", &pnew_end_bal,
                          "end-cleared-balance", &pnew_end_c_bal,
                          "end-reconciled-balance", &pnew_end_r_bal,
                          NULL );

            if ( !gnc_numeric_eq( *pnew_end_bal, balns->end_bal ) )
            {
                adj = gnc_numeric_sub( balns->end_bal, *pnew_end_bal,
                                       GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                balns->start_bal = gnc_numeric_add( balns->start_bal, adj,
                                                    GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                g_object_set( balns->acc, "start-balance", &balns->start_bal, NULL );
            }
            if ( !gnc_numeric_eq( *pnew_end_c_bal, balns->end_cleared_bal ) )
            {
                adj = gnc_numeric_sub( balns->end_cleared_bal, *pnew_end_c_bal,
                                       GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                balns->start_cleared_bal = gnc_numeric_add( balns->start_cleared_bal, adj,
                                           GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                g_object_set( balns->acc, "start-cleared-balance", &balns->start_cleared_bal, NULL );
            }
            if ( !gnc_numeric_eq( *pnew_end_r_bal, balns->end_reconciled_bal ) )
            {
                adj = gnc_numeric_sub( balns->end_reconciled_bal, *pnew_end_r_bal,
                                       GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                balns->start_reconciled_bal = gnc_numeric_add( balns->start_reconciled_bal, adj,
                                              GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                g_object_set( balns->acc, "start-reconciled-balance", &balns->start_reconciled_bal, NULL );
            }
            xaccAccountRecomputeBalance( balns->acc );
            g_free( pnew_end_bal );
            g_free( pnew_end_c_bal );
            g_free( pnew_end_r_bal );
            g_free( balns );
        }
        if ( bal_list != NULL )
        {
            g_slist_free( bal_list );
        }

        xaccAccountCommitEdit( root );
        qof_event_resume();
#endif
    }
}
コード例 #15
0
/*@ null @*/ GSList*
gnc_sql_get_account_balances_slist( GncSqlBackend* be )
{
#if LOAD_TRANSACTIONS_AS_NEEDED
    GncSqlResult* result;
    GncSqlStatement* stmt;
    gchar* buf;
    GSList* bal_slist = NULL;

    g_return_val_if_fail( be != NULL, NULL );

    buf = g_strdup_printf( "SELECT account_guid, reconcile_state, sum(quantity_num) as quantity_num, quantity_denom FROM %s GROUP BY account_guid, reconcile_state, quantity_denom ORDER BY account_guid, reconcile_state",
                           SPLIT_TABLE );
    stmt = gnc_sql_create_statement_from_sql( be, buf );
    g_assert( stmt != NULL );
    g_free( buf );
    result = gnc_sql_execute_select_statement( be, stmt );
    gnc_sql_statement_dispose( stmt );
    if ( result != NULL )
    {
        GncSqlRow* row;
        acct_balances_t* bal = NULL;

        row = gnc_sql_result_get_first_row( result );
        while ( row != NULL )
        {
            single_acct_balance_t* single_bal;

            // Get the next reconcile state balance and merge with other balances
            single_bal = load_single_acct_balances( be, row );
            if ( single_bal != NULL )
            {
                if ( bal != NULL && bal->acct != single_bal->acct )
                {
                    bal->cleared_balance = gnc_numeric_add( bal->cleared_balance, bal->reconciled_balance,
                                                            GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                    bal->balance = gnc_numeric_add( bal->balance, bal->cleared_balance,
                                                    GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                    bal_slist = g_slist_append( bal_slist, bal );
                    bal = NULL;
                }
                if ( bal == NULL )
                {
                    bal = g_malloc( (gsize)sizeof(acct_balances_t) );
                    g_assert( bal != NULL );

                    bal->acct = single_bal->acct;
                    bal->balance = gnc_numeric_zero();
                    bal->cleared_balance = gnc_numeric_zero();
                    bal->reconciled_balance = gnc_numeric_zero();
                }
                if ( single_bal->reconcile_state == 'n' )
                {
                    bal->balance = gnc_numeric_add( bal->balance, single_bal->balance,
                                                    GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                }
                else if ( single_bal->reconcile_state == 'c' )
                {
                    bal->cleared_balance = gnc_numeric_add( bal->cleared_balance, single_bal->balance,
                                                            GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                }
                else if ( single_bal->reconcile_state == 'y' )
                {
                    bal->reconciled_balance = gnc_numeric_add( bal->reconciled_balance, single_bal->balance,
                                              GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
                }
                g_free( single_bal );
            }
            row = gnc_sql_result_get_next_row( result );
        }

        // Add the final balance
        if ( bal != NULL )
        {
            bal->cleared_balance = gnc_numeric_add( bal->cleared_balance, bal->reconciled_balance,
                                                    GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
            bal->balance = gnc_numeric_add( bal->balance, bal->cleared_balance,
                                            GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
            bal_slist = g_slist_append( bal_slist, bal );
        }
        gnc_sql_result_dispose( result );
    }

    return bal_slist;
#else
    return NULL;
#endif
}
コード例 #16
0
ファイル: gnc-account-sql.cpp プロジェクト: CAARNICL/gnucash
static void
load_all_accounts (GncSqlBackend* be)
{
    GncSqlStatement* stmt = NULL;
    GncSqlResult* result;
    QofBook* pBook;
    GList* l_accounts_needing_parents = NULL;
    GSList* bal_slist;
    GSList* bal;

    g_return_if_fail (be != NULL);

    ENTER ("");

    pBook = be->book;

    stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
    if (stmt == NULL)
    {
        LEAVE ("stmt == NULL");
        return;
    }
    result = gnc_sql_execute_select_statement (be, stmt);
    gnc_sql_statement_dispose (stmt);
    if (result != NULL)
    {
        GncSqlRow* row = gnc_sql_result_get_first_row (result);
        gchar* sql;

        while (row != NULL)
        {
            load_single_account (be, row, &l_accounts_needing_parents);
            row = gnc_sql_result_get_next_row (result);
        }
        gnc_sql_result_dispose (result);

        sql = g_strdup_printf ("SELECT DISTINCT guid FROM %s", TABLE_NAME);
        gnc_sql_slots_load_for_sql_subquery (be, sql, (BookLookupFn)xaccAccountLookup);
        g_free (sql);

        /* While there are items on the list of accounts needing parents,
           try to see if the parent has now been loaded.  Theory says that if
           items are removed from the front and added to the back if the
           parent is still not available, then eventually, the list will
           shrink to size 0. */
        if (l_accounts_needing_parents != NULL)
        {
            gboolean progress_made = TRUE;
            Account* root;
            Account* pParent;
            GList* elem;

            while (progress_made)
            {
                progress_made = FALSE;
                for (elem = l_accounts_needing_parents; elem != NULL;)
                {
                    account_parent_guid_struct* s = (account_parent_guid_struct*)elem->data;
                    pParent = xaccAccountLookup (&s->guid, be->book);
                    if (pParent != NULL)
                    {
                        GList* next_elem;

                        gnc_account_append_child (pParent, s->pAccount);
                        next_elem = g_list_next (elem);
                        l_accounts_needing_parents = g_list_delete_link (l_accounts_needing_parents,
                                                                         elem);
                        g_free (s);
                        elem = next_elem;
                        progress_made = TRUE;
                    }
                    else
                    {
                        /* Can't be up in the for loop because the 'then' clause reads inside a node freed
                           by g_list_delete_link(). */
                        elem = g_list_next (elem);
                    }
                }
            }

            /* Any non-ROOT accounts left over must be parented by the root account */
            root = gnc_book_get_root_account (pBook);
            while (l_accounts_needing_parents != NULL)
            {
                account_parent_guid_struct* s = (account_parent_guid_struct*)
                                                l_accounts_needing_parents->data;
                if (xaccAccountGetType (s->pAccount) != ACCT_TYPE_ROOT)
                {
                    gnc_account_append_child (root, s->pAccount);
                }
                g_free (s);
                l_accounts_needing_parents = g_list_delete_link (l_accounts_needing_parents,
                                                                 l_accounts_needing_parents);
            }
        }

        /* Load starting balances */
        bal_slist = gnc_sql_get_account_balances_slist (be);
        for (bal = bal_slist; bal != NULL; bal = bal->next)
        {
            acct_balances_t* balances = (acct_balances_t*)bal->data;

            qof_instance_increase_editlevel (balances->acct);
            g_object_set (balances->acct,
                          "start-balance", &balances->balance,
                          "start-cleared-balance", &balances->cleared_balance,
                          "start-reconciled-balance", &balances->reconciled_balance,
                          NULL);

            qof_instance_decrease_editlevel (balances->acct);
        }
        if (bal_slist != NULL)
        {
            g_slist_free (bal_slist);
        }
    }

    LEAVE ("");
}