int
find_text( db_t hdb, const char * textid, const char * locale )
{
    int rc = EXIT_FAILURE;
    db_result_t db_rc = DB_OK;
    db_row_t row;
    db_cursor_t c;
    db_table_cursor_t p = {
        STORAGE_PKEY_INDEX_NAME,   //< No index
        DB_SCAN_FORWARD | DB_LOCK_EXCLUSIVE
    };
    char en[MAX_TEXT_LEN + 1] = {0};
    char tr[MAX_TEXT_LEN + 1] = {0};

    int target_fno = EN_FNO;
    if( 0 == strncmp( "jp", locale, 2 ) ) {
        target_fno = JP_FNO;
    }
    else if( 0 == strncmp( "fr", locale, 2 ) ) {
        target_fno = FR_FNO;
    }
    else if( 0 == strncmp( "es", locale, 2 ) ) {
        target_fno = ES_FNO;
    }
    else if( 0 == strncmp( "ru", locale, 2 ) ) {
        target_fno = RU_FNO;
    }

    c = db_open_table_cursor(hdb, STORAGE_TABLE, &p);

    row = db_alloc_row( NULL, 2 );
    if( NULL == row ) {
        print_error_message( "Couldn't pupulate 'storage' table\n" );
        return EXIT_FAILURE;
    }

    dbs_bind_addr( row, ID_FNO, DB_VARTYPE_ANSISTR, (char*)textid, strlen(textid), NULL );
    if( DB_OK == db_seek( c, DB_SEEK_FIRST_EQUAL, row, 0, 1 ) )
    {
        db_unbind_field( row, ID_FNO );
        dbs_bind_addr( row, EN_FNO, DB_VARTYPE_UTF8STR, en, MAX_TEXT_LEN, NULL );
        if( target_fno != EN_FNO ) {
            dbs_bind_addr( row, target_fno, DB_VARTYPE_UTF8STR, tr, MAX_TEXT_LEN, NULL );
        }
        if( DB_OK == db_fetch( c, row, 0 ) ) {
            fprintf( stdout, "Message. Id: %s, en: [%s], %s: [%s]\n",
                     textid, en, locale, target_fno == EN_FNO ? "" : tr
                     );
            rc = EXIT_SUCCESS;
        }
    }
    if( rc != EXIT_SUCCESS ) {
        print_error_message( "Couldn't find translated text for messageid %s\n", textid );
    }

    db_free_row( row );
    db_close_cursor( c );

    return rc;
}
Exemple #2
0
/**
 * Convert a row from the result query into db API representation
 */
int db_postgres_convert_row(const db_con_t* _h, db_res_t* _r, db_row_t* _row,
		char **row_buf)
{
	int col, len;

	if (!_h || !_r || !_row)  {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	/* Save the number of columns in the ROW structure */
	ROW_N(_row) = RES_COL_N(_r);

	/* For each column in the row */
	for(col = 0; col < ROW_N(_row); col++) {
		/* compute the len of the value */
		if ( row_buf[col]==NULL || row_buf[col][0]=='\0')
			len = 0;
		else
			len =  strlen(row_buf[col]);

		/* Convert the string representation into the value representation */
		if (db_postgres_str2val(RES_TYPES(_r)[col], &(ROW_VALUES(_row)[col]),
		row_buf[col], len) < 0) {
			LM_ERR("failed to convert value\n");
			LM_DBG("free row at %pn", _row);
			db_free_row(_row);
			return -3;
		}
	}
	return 0;
}
int
load_data( db_t hdb )
{
    db_result_t rc = DB_OK;
    int i;

    db_row_t row;
    db_table_cursor_t p = {
        NULL,   //< No index
        DB_CAN_MODIFY | DB_LOCK_EXCLUSIVE
    };
    db_cursor_t c;

    c = db_open_table_cursor(hdb, STORAGE_TABLE, &p);

    row = db_alloc_row( binds_def, DB_ARRAY_DIM( binds_def ) );
    if( NULL == row ) {
        print_error_message( "Couldn't allocate row to pupulate 'storage' table\n" );
        return EXIT_FAILURE;
    }

    for( i = 0; i < DB_ARRAY_DIM(texts) && DB_OK == rc; ++i ) {
        rc = db_insert(c, row, &texts[i], 0);
    }

    db_free_row( row );
    rc = DB_OK == rc ? db_commit_tx( hdb, 0 ) : rc;

    if( DB_OK != rc ) {
        print_error_message( "Couldn't pupulate 'storage' table\n" );
    }
    db_close_cursor(c);

    return DB_OK == rc ? EXIT_SUCCESS : EXIT_FAILURE;
}
Exemple #4
0
/*!
 * \brief Convert a row from result into DB API representation
 * \param _h database connection
 * \param _res database result in the DB API representation
 * \param _r database result row
 * \return 0 on success, -1 on failure
 */
int db_mysql_convert_row(const db1_con_t* _h, db1_res_t* _res, db_row_t* _r)
{
	unsigned long* lengths;
	int i;

	if ((!_h) || (!_res) || (!_r)) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	if (db_allocate_row(_res, _r) != 0) {
		LM_ERR("could not allocate row");
		return -2;
	}
	
	lengths = mysql_fetch_lengths(CON_RESULT(_h));

	for(i = 0; i < RES_COL_N(_res); i++) {
		if (db_str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]),
			    ((MYSQL_ROW)CON_ROW(_h))[i], lengths[i], 0) < 0) {
			LM_ERR("failed to convert value\n");
			LM_DBG("free row at %p\n", _r);
			db_free_row(_r);
			return -3;
		}
	}
	return 0;
}
Exemple #5
0
/*!
 * \brief Convert a row from the result query into db API representation
 * \param _h database connection
 * \param _r result set
 * \param _row row
 * \param row_buf row buffer
 * \return 0 on success, negative on error
 */
int db_postgres_convert_row(const db1_con_t* _h, db1_res_t* _r, db_row_t* _row,
                            char **row_buf)
{
    int col, col_len;

    if (!_h || !_r || !_row)  {
        LM_ERR("invalid parameter value\n");
        return -1;
    }

    if (db_allocate_row(_r, _row) != 0) {
        LM_ERR("could not allocate row\n");
        return -2;
    }

    /* For each column in the row */
    for(col = 0; col < ROW_N(_row); col++) {
        /* because it can contain NULL */
        if (!row_buf[col]) {
            col_len = 0;
        } else {
            col_len = strlen(row_buf[col]);
        }
        /* Convert the string representation into the value representation */
        if (db_postgres_str2val(RES_TYPES(_r)[col], &(ROW_VALUES(_row)[col]),
                                row_buf[col], col_len) < 0) {
            LM_ERR("failed to convert value\n");
            LM_DBG("free row at %p\n", _row);
            db_free_row(_row);
            return -3;
        }
    }
    return 0;
}
Exemple #6
0
int
populate_data( db_t hdb )
{
    db_result_t rc = DB_OK;
    int i;

    /* Populate "storage" table using relative bounds fields. See
       ittiadb/manuals/users-guide/api-c-database-access.html#relative-bound-fields
     */
    typedef struct {
        db_ansi_t   f0[MAX_STRING_FIELD + 1];   /* Extra char for null termination. */
        uint64_t    f1;
        double      f2;
        char        f3[MAX_STRING_FIELD*2 + 1];
    } storage_t;

    static const db_bind_t binds_def[] = {
        { 0, DB_VARTYPE_ANSISTR,  DB_BIND_OFFSET( storage_t, f0 ),  DB_BIND_SIZE( storage_t, f0 ), -1, DB_BIND_RELATIVE },
        { 1, DB_VARTYPE_SINT64,   DB_BIND_OFFSET( storage_t, f1 ),  DB_BIND_SIZE( storage_t, f1 ), -1, DB_BIND_RELATIVE },
        { 2, DB_VARTYPE_FLOAT64,  DB_BIND_OFFSET( storage_t, f2 ),  DB_BIND_SIZE( storage_t, f2 ), -1, DB_BIND_RELATIVE },
        { 3, DB_VARTYPE_UTF8STR,  DB_BIND_OFFSET( storage_t, f3 ),  DB_BIND_SIZE( storage_t, f3 ), -1, DB_BIND_RELATIVE },
    };

    static storage_t rows2ins[] = {
        { "ansi_str1",  1,  1.231, "utf8" },
        { "ansi_str2",    2,  2.231, "utf8" },
        { "ansi_str3",    3,  3.231, "УТФ-8" },
        { "ansi_str4",    4,  4.231, "utf8" },
        { "ansi_str5",    5,  5.231, "utf8" },
    };
    db_row_t row;
    db_table_cursor_t p = {
        NULL,   //< No index
        DB_CAN_MODIFY | DB_LOCK_EXCLUSIVE
    };
    db_cursor_t c;

    row = db_alloc_row( binds_def, DB_ARRAY_DIM( binds_def ) );
    if( NULL == row ) {
        print_error_message( "Couldn't pupulate 'storage' table\n" );
        return EXIT_FAILURE;
    }

    c = db_open_table_cursor(hdb, STORAGE_TABLE, &p);

    for( i = 0; i < DB_ARRAY_DIM(rows2ins) && DB_OK == rc; ++i ) {
        rc = db_insert(c, row, &rows2ins[i], 0);
    }

    db_free_row( row );
    rc = DB_OK == rc ? db_commit_tx( hdb, 0 ) : rc;

    if( DB_OK != rc ) {
        print_error_message( "Couldn't pupulate 'storage' table\n" );
    }
    db_close_cursor(c);

    return DB_OK == rc ? EXIT_SUCCESS : EXIT_FAILURE;
}
int
perform_transactions( db_t hdb, trans_stat_t *stat )
{
    int i;
    db_row_t row;
    db_table_cursor_t p = {
        NULL,   //< No index
        DB_CAN_MODIFY | DB_LOCK_EXCLUSIVE
    };
    db_cursor_t c;
    db_result_t db_rc;
    storage_t row2ins = { "ansi_str1",  1,  1.231, "utf8" };

    // Allocate row. binds_def see in db_schema.h
    row = db_alloc_row( binds_def, DB_ARRAY_DIM( binds_def ) );
    if( NULL == row ) {
        print_error_message( "Couldn't allocate db_row_t\n", NULL );
        return EXIT_FAILURE;
    }

    // Open cursor
    c = db_open_table_cursor(hdb, STORAGE_TABLE, &p);

    db_rc = DB_OK;
    for( i = 0; i < 100 && DB_OK == db_rc; ++i ) {
        int do_lazy_commit = i % 5;
        db_rc = db_begin_tx( hdb, 0 );
        row2ins.f1 = i+1;
        row2ins.f2 = do_lazy_commit ? 50 : 16;
        db_rc = db_insert(c, row, &row2ins, 0);
        db_commit_tx( hdb, do_lazy_commit ? DB_LAZY_COMPLETION : DB_DEFAULT_COMPLETION );
        if( do_lazy_commit ) {
            stat->lazy_tx++;
        }
        else {
            stat->forced_tx++;
        }

        if( i % 30 ) {
            db_flush_tx( hdb, DB_FLUSH_JOURNAL );
        }
    }

    if( DB_OK != db_rc ) {
        print_error_message( "Error inserting or commiting\n", c );
    }

    db_close_cursor( c );
    db_free_row( row );

    return DB_OK == db_rc ? EXIT_SUCCESS : EXIT_FAILURE;
}
Exemple #8
0
/**
 * Convert a row from result into db API representation
 */
int db_mysql_convert_row(const db_con_t* _h, db_res_t* _res, db_row_t* _r)
{
	unsigned long* lengths;
	int i;

	if ((!_h) || (!_res) || (!_r)) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	/* Save the number of columns in the ROW structure */
	ROW_N(_r) = RES_COL_N(_res);

	if (CON_HAS_PS(_h)) {
		for(i=0; i < CON_MYSQL_PS(_h)->cols_out; i++) {
			if (db_mysql_str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]),
			CON_PS_OUTCOL(_h, i).null?NULL:CON_PS_OUTCOL(_h, i).buf,
			CON_PS_OUTCOL(_h,i).len) < 0) {
				LM_ERR("failed to convert value from stmt\n");
				db_free_row(_r);
				return -3;
			}
		}
	} else {
		lengths = mysql_fetch_lengths(CON_RESULT(_h));
		for(i = 0; i < RES_COL_N(_res); i++) {
			if (db_mysql_str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]),
			((MYSQL_ROW)CON_ROW(_h))[i], lengths[i]) < 0) {
				LM_ERR("failed to convert value\n");
				LM_DBG("free row at %p\n", _r);
				db_free_row(_r);
				return -3;
			}
		}
	}
	return 0;
}
Exemple #9
0
/*
 * Release memory used by rows
 */
int db_free_rows(db_res_t* _r)
{
    int i;

    if (!_r) {
        LM_ERR("invalid parameter value\n");
        return -1;
    }
    LM_DBG("freeing %d rows\n", RES_ROW_N(_r));

    if (RES_ROWS(_r)) {
        for(i = 0; i < RES_ROW_N(_r); i++)
            db_free_row(&(RES_ROWS(_r)[i]));

        LM_DBG("freeing rows at %p\n", RES_ROWS(_r));
        pkg_free(RES_ROWS(_r));
        RES_ROWS(_r) = NULL;
    }

    RES_ROW_N(_r) = 0;

    return 0;
}
Exemple #10
0
/*
 * Convert a row from result into db API representation
 */
int db_unixodbc_convert_row(const db_con_t* _h, const db_res_t* _res, 
									db_row_t* _r, const unsigned long* lengths)
{
	int i;

	if ((!_h) || (!_res) || (!_r)) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	/* Save the number of columns in the ROW structure */
	ROW_N(_r) = RES_COL_N(_res);
	for(i = 0; i < RES_COL_N(_res); i++) {
		if (db_unixodbc_str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]),
			((CON_ROW(_h))[i]), lengths[i]) < 0) {
			LM_ERR("failed to convert value\n");
			LM_DBG("free row at %p\n", _r);
			db_free_row(_r);
			return -3;
		}
	}
	return 0;
}
Exemple #11
0
/*
 * Release memory used by rows
 */
inline int db_free_rows(db_res_t* _r)
{
	int i;

	if (!_r) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}
	LM_DBG("freeing %d rows\n", RES_ROW_N(_r));

	for(i = 0; i < RES_ROW_N(_r); i++) {
		LM_DBG("row[%d]=%p\n", i, &(RES_ROWS(_r)[i]));
		db_free_row(&(RES_ROWS(_r)[i]));
	}
	RES_ROW_N(_r) = 0;

	if (RES_ROWS(_r)) {
		LM_DBG("%p=pkg_free() RES_ROWS\n", RES_ROWS(_r));
		pkg_free(RES_ROWS(_r));
		RES_ROWS(_r) = NULL;
	}
	return 0;
}
int check_data( db_t hdb, const trans_stat_t * stat )
{
    int rc = EXIT_FAILURE;
    db_result_t db_rc = DB_OK;

    db_row_t row;

    storage_t row_data;
    db_cursor_t c;  // Cursor to scan table to check
    // Cursor parameters
    db_table_cursor_t p = {
        PKEY_INDEX_NAME,   //< Index by which to sort the table
        DB_SCAN_FORWARD | DB_LOCK_DEFAULT
    };

    // Open cursor
    c = db_open_table_cursor(hdb, STORAGE_TABLE, &p);
    row = db_alloc_row( binds_def, DB_ARRAY_DIM( binds_def ) );

    db_rc = db_seek_first(c);

    // Scan table and check that pkey values are monotonically increase
    {
        int counter = 0;
        trans_stat_t s = { 0, 0 };
        for(; !db_eof(c) && DB_OK == db_rc; db_rc = db_seek_next(c) )
        {
            db_rc = db_fetch(c, row, &row_data);
            if( row_data.f1 != ++counter ) {
                break;
            }
            s.lazy_tx += row_data.f2 == 50 ? 1 : 0;
            s.forced_tx += row_data.f2 == 16 ? 1 : 0;
        }

        if( DB_OK != db_rc ) {
            print_error_message( "Error to scan table of backup db\n", c );
        }
        else if( row_data.f1 != counter ) {
            fprintf( stderr, "Pkey field values sequence violation detected in backup db: (%" PRId64 ", %d)\n",
                     row_data.f1, counter
                     );
        }
        else if( s.lazy_tx != stat->lazy_tx ) {
            fprintf( stderr, "Unexpected count of records which was commited in lazy-commit mode: %d, but expected %d.\n",
                     s.lazy_tx, stat->lazy_tx );
        }
        else if( s.forced_tx != stat->forced_tx ) {
            fprintf( stderr, "Unexpected count of records which was commited in force-commit mode: %d, but expected %d.\n",
                     s.forced_tx, stat->forced_tx );
        }
        else {
            fprintf( stdout, "%d records is inside\n", counter );
            rc = EXIT_SUCCESS;
        }
    }

    db_close_cursor( c );
    db_free_row( row );
    db_shutdown(hdb, DB_SOFT_SHUTDOWN, NULL);

    return rc;
}
Exemple #13
0
static db_result_t
upgrade_to_schema_v2( db_t hdb )
{
    db_result_t rc = DB_OK;
    /* 1. Convert string type v1's 'sex_title' column to int-type 'sex' column, as v2 schema declares */
    /* 1.1. Append a new uint8 type 'sex' column */
    db_fielddef_t sex = { CONTACT_NFIELDS, "sex", DB_COLTYPE_UINT8, 0, 0, DB_NULLABLE, 0 };

    /* 1.2. Fill 'sex' column with data according to schema: Mr->0, Mrs->1,Other->2 */
    // Use absolute bound fields ( see ittiadb/manuals/users-guide/api-c-database-access.html#absolute-bound-fields )
    db_ansi_t sex_old[ MAX_SEX_TITLE + 1 ];
    db_len_t sex_ind = DB_FIELD_NULL, sex_ind_new = DB_FIELD_NULL;
    uint8_t sex_new = 0;
    db_bind_t binds_def[] = {
        {CONTACT_SEX, DB_VARTYPE_ANSISTR, DB_BIND_ADDRESS(sex_old), sizeof(sex_old), DB_BIND_ADDRESS(&sex_ind), DB_BIND_ABSOLUTE},
        {CONTACT_NFIELDS, DB_VARTYPE_UINT8, DB_BIND_ADDRESS(&sex_new), sizeof(sex_new), DB_BIND_ADDRESS(&sex_ind_new),   DB_BIND_ABSOLUTE},
    };
    db_row_t row = db_alloc_row( binds_def, 2 );

    db_table_cursor_t p = {
        NULL,   //< No index
        DB_CAN_MODIFY | DB_LOCK_EXCLUSIVE
    };
    db_cursor_t c;

    rc = db_add_field( hdb, CONTACT_TABLE, &sex );
    if( DB_OK != rc ) {
        print_error_message( "Couldn't append 'sex' column on v1->v2 upgrade", 0 );
        return DB_FAIL;
    }

    c = db_open_table_cursor(hdb, CONTACT_TABLE, &p);

    db_begin_tx( hdb, DB_DEFAULT_ISOLATION | DB_LOCK_DEFAULT );
    for ( rc = db_seek_first( c ); DB_OK == rc && !db_eof( c ); db_seek_next( c ) ) {
        rc = db_fetch( c, row, 0 );
        if( 0 == strcmp( "Mr", sex_old ) ) {
            sex_new = 0;
        }
        else if( 0 == strcmp( "Mrs", sex_old ) ) {
            sex_new = 1;
        }
        else {
            sex_new = 2;
        }
        sex_ind_new = 0;
        rc = db_update( c, row, 0 );
    }
    db_commit_tx( hdb, DB_DEFAULT_COMPLETION );

    if( DB_OK != rc ) {
        print_error_message( "Couldn't fill appended 'sex' column with data", c );
    }

    db_free_row( row );
    db_close_cursor( c );


    /* 1.3 Drop v1 sex_title column. */
    /* Note: Dropping columns isn't available in ITTIA evaluation version. */
    rc = db_drop_field( hdb, CONTACT_TABLE, "sex_title" );
    if( DB_OK != rc ) {
        if( DB_EEVALUATION == get_db_error() ) {
            rc = DB_OK;
            fprintf( stdout, "No db_drop_field() feature supported in ITTIA Evaluation version\n" );
        }
        else {
            print_error_message( "Couldn't drop 'sex_title' v1 schema column", c );
        }
    }

    /* 2. Indexes modifications */
    // 2.1. drop old pkey
    rc = db_drop_index( hdb, CONTACT_TABLE, CONTACT_BY_ID );
    if ( DB_OK != rc ) {
        print_error_message( "Couldn't drop v1 pkey index", c );
    }

    // 2.2. create a new one
    // 2.2.1. Set NOT NULL property on ring_id field
    // Note: this feature isn't supported in evaluation version of ittiadb.
    {
        extern db_fielddef_t contact_fields[];   //< Defined in schema_upgrade_schema_v2.c
        rc = db_update_field( hdb, CONTACT_TABLE, "ring_id", &contact_fields[ CONTACT_RING_ID ] );

        if ( DB_OK != rc ) {
            print_error_message( "Couldn't set not null on ring_id column", c );
        }
    }

    // 2.2.2. Create PKey index
    {
        extern db_indexdef_t contact_indexes[];  //< Defined in schema_upgrade_schema_v2.c
        rc = db_create_index( hdb, CONTACT_TABLE, CONTACT_BY_ID_RING_ID, &contact_indexes[0] );

        if ( DB_OK != rc ) {
            print_error_message( "Couldn't create v2 pkey index", c );
        }
    }
}
Exemple #14
0
int
init_data_cb( db_t hdb, int version )
{
    db_result_t rc = DB_OK;
    int i;

    /* Populate "contact" table using relative bounds fields. See
       ittiadb/manuals/users-guide/api-c-database-access.html#relative-bound-fields
     */
    static const db_bind_t binds_def[] = {
        { CONTACT_ID,         DB_VARTYPE_UINT64,    DB_BIND_OFFSET( contact_t, id ),        DB_BIND_SIZE( contact_t, id ),      -1, DB_BIND_RELATIVE },
        { CONTACT_NAME,       DB_VARTYPE_WCHARSTR,  DB_BIND_OFFSET( contact_t, name ),      DB_BIND_SIZE( contact_t, name ),    -1, DB_BIND_RELATIVE },
        { CONTACT_RING_ID,    DB_VARTYPE_UINT64,    DB_BIND_OFFSET( contact_t, ring_id ),   DB_BIND_SIZE( contact_t, ring_id ), -1, DB_BIND_RELATIVE },
        { CONTACT_SEX,        DB_VARTYPE_ANSISTR,   DB_BIND_OFFSET( contact_t, sex ),       DB_BIND_SIZE( contact_t, sex ),     -1, DB_BIND_RELATIVE },
    };

    contact_t contacts2ins[] = {
        { 1, L"Bob",    1, "Mr"     },
        { 2, L"Alice",  1, "Mrs"    },
        { 3, L"Fred",   1, "Mr"     },
        { 4, L"Mary",   1, "Mrs"    },
    };
    db_row_t row;

    db_table_cursor_t p = {
        NULL,   //< No index
        DB_CAN_MODIFY | DB_LOCK_EXCLUSIVE
    };
    db_cursor_t c;

    if( 1 > version || 2 < version ) {
        print_error_message("Wrong DB schema version. Can't insert data.", NULL);
        return -1;
    }
    fprintf( stdout, "Populating just creating DB v%d with data\n", version );

    row = db_alloc_row( binds_def, DB_ARRAY_DIM( binds_def ) );

    c = db_open_table_cursor(hdb, CONTACT_TABLE, &p);

    for( i = 0; i < DB_ARRAY_DIM(contacts2ins) && DB_OK == rc; ++i ) {
        if( 2 == version ) {
            if( 0 == strcmp( contacts2ins[i].sex, "Mrs" ) ) {
                strcpy( contacts2ins[i].sex, "1" );
            }
            else if( 0 == strcmp( contacts2ins[i].sex, "Mr" ) ) {
                strcpy( contacts2ins[i].sex, "0" );
            }
            else {
                strcpy( contacts2ins[i].sex, "2" );
            }
        }
        rc = db_insert(c, row, &contacts2ins[i], 0);
    }
    db_free_row( row );

    if( DB_OK != rc ) {
        print_error_message( "Couldn't pupulate 'contact' table\n", c );
    }

    db_close_cursor(c);

    return DB_OK == rc ? 0 : -1;
}