DBD-cubrid

 view release on metacpan or  search on metacpan

dbdimp.c  view on Meta::CPAN

    } else {
        /* cci_last_id set last_id as allocated string */
        res = cci_last_insert_id (imp_dbh->handle, &name, &error);
    }
    
    if (res < 0) {
        handle_error (dbh, res, &error);
        return Nullsv;
    }

    if (!name) {
        return Nullsv;
    } else {
        sv = newSVpvn (name, strlen(name));

        /* free last_id which is allocated in cci_last_insert_id */
        if (cci_get_last_insert_id_fp == NULL) {
#ifndef WIN32
            free(name);
#endif
        }
    }

    return sv_2mortal (sv);
}

/**************************************************************************
 *
 * Name:    dbd_db_ping
 *
 * Purpose: Check whether the database server is still running and the 
 *          connection to it is still working.
 *
 * Input:   Nothing
 *
 * Returns: TRUE for success, FALSE otherwise
 *
 **************************************************************************/

int
dbd_db_ping( SV *dbh )
{
    int res;
    T_CCI_ERROR error;
    char *query = "SELECT 1+1 from db_root /*+ shard_id(0) */";
    int req_handle = 0, result = 0, ind = 0;

    D_imp_dbh (dbh);

    if ((res = cci_prepare (imp_dbh->handle, query, 0, &error)) < 0) {
		goto ER_DB_PING;
    }

    req_handle = res;

    if ((res = cci_execute (req_handle, 0, 0, &error)) < 0) {
        goto ER_DB_PING;
    }

    while (1) {
        res = cci_cursor (req_handle, 1, CCI_CURSOR_CURRENT, &error);
        if (res == CCI_ER_NO_MORE_DATA) {
            break;
        }
        if (res < 0) {
            goto ER_DB_PING;
        }

        if ((res = cci_fetch (req_handle, &error)) < 0) {
            goto ER_DB_PING;
        }

        if ((res = cci_get_data (req_handle, 1, CCI_A_TYPE_INT, &result, &ind)) < 0) {
            goto ER_DB_PING;
        }

        if (result == 2) {
            cci_close_req_handle (req_handle);
            return TRUE;
        }
    }
	cci_close_req_handle (req_handle);
ER_DB_PING:
    handle_error (dbh, res, &error);
    return FALSE;
}

/***************************************************************************
 *
 * Name:    dbd_st_prepare
 *
 * Purpose: Called for preparing an SQL statement; our part of the
 *          statement handle constructor
 *
 * Input:   sth - statement handle being initialized
 *          imp_sth - drivers private statement handle data
 *          statement - pointer to string with SQL statement
 *          attribs - statement attributes, currently not in use
 *
 * Returns: TRUE for success, FALSE otherwise
 *
 **************************************************************************/

int
dbd_st_prepare( SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs )
{
    int res;
    T_CCI_ERROR error;

    D_imp_dbh_from_sth;

    if ('\0' == *statement)
        croak ("Cannot preapre empty statement");

    imp_sth->conn = imp_dbh->handle;

    imp_sth->col_count = -1;
    imp_sth->sql_type = 0;
    imp_sth->affected_rows = -1;
    imp_sth->lob = NULL;

dbdimp.c  view on Meta::CPAN


    DBIc_NUM_PARAMS(imp_sth) = cci_get_bind_num (res);

    DBIc_IMPSET_on(imp_sth);

    return TRUE;
}

/***************************************************************************
 *
 * Name:    dbd_st_execute
 *
 * Purpose: Called for execute the prepared SQL statement; our part of
 *          the statement handle constructor
 *
 * Input:   sth - statement handle
 *          imp_sth - drivers private statement handle data
 *
 * Returns: TRUE for success, FALSE otherwise
 *
 **************************************************************************/

int
dbd_st_execute( SV *sth, imp_sth_t *imp_sth )
{
    int res, option = 0, max_col_size = 0;
    T_CCI_ERROR error;
    T_CCI_COL_INFO *col_info;
    T_CCI_SQLX_CMD sql_type;
    int col_count;

    if ((res = cci_execute (imp_sth->handle, option, 
                    max_col_size, &error)) < 0) {
        handle_error (sth, res, &error);
        return -2;
    }

    col_info = cci_get_result_info (imp_sth->handle, &sql_type, &col_count);
    if (sql_type == SQLX_CMD_SELECT && !col_info) {
        handle_error(sth, CUBRID_ER_CANNOT_GET_COLUMN_INFO, NULL);
        return -2;
    }

    imp_sth->col_info = col_info;
    imp_sth->sql_type = sql_type;
    imp_sth->col_count = col_count;

    switch (sql_type) {
    case SQLX_CMD_INSERT:
    case SQLX_CMD_UPDATE:
    case SQLX_CMD_DELETE:
    case SQLX_CMD_CALL:
    case SQLX_CMD_SELECT:
        imp_sth->affected_rows = res;
        break;
    default:
        imp_sth->affected_rows = -1;
    }

    if (sql_type == SQLX_CMD_SELECT) {
        res = cci_cursor (imp_sth->handle, 1, CCI_CURSOR_CURRENT, &error);
        if (res < 0 && res != CCI_ER_NO_MORE_DATA) {
            handle_error (sth, res, &error);
            return -2;
        }

        DBIc_NUM_FIELDS (imp_sth) = col_count;
        DBIc_ACTIVE_on (imp_sth);
    }
    
    return imp_sth->affected_rows;
}

/***************************************************************************
 *
 * Name:    dbd_st_fetch
 *
 * Purpose: Called for execute the prepared SQL statement; our part of
 *          the statement handle constructor
 *
 * Input:   sth - statement handle being initialized
 *          imp_sth - drivers private statement handle data
 *
 * Returns: array of columns; the array is allocated by DBI via
 *          DBIS->get_fbav(imp_sth), even the values of the array
 *          are prepared, we just need to modify them appropriately
 *
 **************************************************************************/

AV *
dbd_st_fetch( SV *sth, imp_sth_t *imp_sth )
{
    AV *av;
    int res;
    T_CCI_ERROR error;

    if (DBIc_ACTIVE(imp_sth)) {
        DBIc_ACTIVE_off(imp_sth);
    }

    res = cci_cursor (imp_sth->handle, 0, CCI_CURSOR_CURRENT, &error);
    if (res == CCI_ER_NO_MORE_DATA) {
        return Nullav;
    } else if (res < 0) {
        goto ERR_ST_FETCH;
    }

    if ((res = cci_fetch (imp_sth->handle, &error)) < 0) {
        goto ERR_ST_FETCH;
    }

    av = DBIS->get_fbav(imp_sth);
    if ((res = _cubrid_fetch_row (av, 
                                  imp_sth->handle, 
                                  imp_sth->col_count, 
                                  imp_sth->col_info, 
                                  &error)) < 0) {
        goto ERR_ST_FETCH;
    }

    res = cci_cursor (imp_sth->handle, 1, CCI_CURSOR_CURRENT, &error);
    if (res < 0 && res != CCI_ER_NO_MORE_DATA) {
        goto ERR_ST_FETCH;
    }

    return av;
ERR_ST_FETCH:
    handle_error (sth, res, &error);
    return Nullav;	  
}

/***************************************************************************
 *
 * Name:    dbd_st_finish
 *
 * Purpose: Called for freeing a CUBRID result
 *
 * Input:   sth - statement handle being finished
 *          imp_sth - drivers private statement handle data
 *
 * Returns: TRUE for success, FALSE otherwise
 *
 **************************************************************************/

int
dbd_st_finish( SV *sth, imp_sth_t *imp_sth )
{
    if (!DBIc_ACTIVE(imp_sth))
        return TRUE;

    DBIc_ACTIVE_off(imp_sth);

    return TRUE;
}

/***************************************************************************
 *
 * Name:    dbd_st_destroy
 *
 * Purpose: Our part of the statement handles destructor
 *
 * Input:   sth - statement handle being destroyed
 *          imp_sth - drivers private statement handle data
 *
 * Returns: Nothing
 *
 **************************************************************************/

void
dbd_st_destroy( SV *sth, imp_sth_t *imp_sth )
{
    if (imp_sth->handle) {
        if (imp_sth->lob) {
            int i;
            for (i = 0; i < imp_sth->affected_rows; i++) {
                _cubrid_lob_free (imp_sth->lob[i].lob, imp_sth->lob[i].type);
            }

            free (imp_sth->lob);
            imp_sth->lob = NULL;
        }

dbdimp.c  view on Meta::CPAN

    D_imp_sth (sth);
    imp_sth->lob = NULL;

    if (col < 1 || col > DBIc_NUM_FIELDS (imp_sth)) {
        handle_error (sth, CCI_ER_COLUMN_INDEX, NULL);
        return FALSE;
    }

    if (imp_sth->sql_type != SQLX_CMD_SELECT) {
        handle_error (sth, CCI_ER_NO_MORE_DATA, NULL);
        return FALSE;
    }

    u_type = CCI_GET_RESULT_INFO_TYPE (imp_sth->col_info, col);
    if (!(u_type == CCI_U_TYPE_BLOB ||  u_type == CCI_U_TYPE_CLOB)) {
        handle_error (sth, CUBRID_ER_NOT_LOB_TYPE, NULL);
        return FALSE;
    }

    imp_sth->col_selected = col;

    imp_sth->lob = (T_CUBRID_LOB *) malloc (imp_sth->affected_rows * sizeof (T_CUBRID_LOB));
    memset(imp_sth->lob, 0, imp_sth->affected_rows * sizeof (T_CUBRID_LOB));

    return TRUE;
}

int
cubrid_st_lob_export( SV *sth, int index, char *filename )
{
    char buf[CUBRID_BUFFER_LEN] = {'\0'};
    int fd, res, size;
    long long pos = 0, lob_size;
    T_CCI_ERROR error;
    T_CCI_U_TYPE u_type;
    int ind = 0;

    D_imp_sth (sth);

    if (imp_sth->lob == NULL) {
        handle_error (sth, CUBRID_ER_CANNOT_FETCH_DATA, NULL);
        return FALSE;
    }

    if (index > imp_sth->affected_rows || index < 1) {
        handle_error (sth, CUBRID_ER_ROW_INDEX_EXCEEDED, NULL);
        return FALSE;
    }

    if (imp_sth->col_selected < 1 || imp_sth->col_selected > DBIc_NUM_FIELDS (imp_sth)) {
        handle_error (sth, CCI_ER_COLUMN_INDEX, NULL);
        return FALSE;
    }

    u_type = CCI_GET_RESULT_INFO_TYPE (imp_sth->col_info, imp_sth->col_selected);
    if (!(u_type == CCI_U_TYPE_BLOB ||  u_type == CCI_U_TYPE_CLOB)) {
        handle_error (sth, CUBRID_ER_NOT_LOB_TYPE, NULL);
        return FALSE;
    }

    res = cci_cursor (imp_sth->handle, index, CCI_CURSOR_FIRST, &error);
    if (res == CCI_ER_NO_MORE_DATA) {
        return TRUE;
    } else if (res < 0) {
        handle_error (sth, res, &error);
        return FALSE;
    }

    if ((res = cci_fetch(imp_sth->handle, &error)) < 0) {
        handle_error (sth, res, &error);
        return FALSE;
    }

    if ( u_type == CCI_U_TYPE_BLOB) {
        imp_sth->lob[index-1].type = CCI_U_TYPE_BLOB;
        if ((res = cci_get_data (imp_sth->handle,
                        imp_sth->col_selected,
                        CCI_A_TYPE_BLOB,
                        (void *)&imp_sth->lob[index-1].lob,
                        &ind)) < 0) {
            handle_error (sth, res, NULL);
            return FALSE;
        }
    } else {
        imp_sth->lob[index-1].type = CCI_U_TYPE_BLOB;
        if ((res = cci_get_data (imp_sth->handle,
                        imp_sth->col_selected,
                        CCI_A_TYPE_CLOB,
                        (void *)&imp_sth->lob[index-1].lob,
                        (&ind))) < 0) {
            handle_error (sth, res, NULL);
            return FALSE;
        }
    }

    if ( ind == -1 ) {
        handle_error (sth, CUBRID_ER_EXPORT_NULL_LOB_INVALID, NULL);
        return FALSE;
    }

    if ( imp_sth->lob == NULL || imp_sth->lob[index-1].lob == NULL) {
        handle_error (sth, CCI_ER_INVALID_LOB_HANDLE, NULL);
        return FALSE;
    }

    if ((fd = open (filename, O_CREAT | O_WRONLY | O_TRUNC, 0666)) < 0) {
        handle_error (sth, CCI_ER_FILE, NULL);
        return FALSE;
    }

    lob_size = _cubrid_lob_size (imp_sth->lob[index-1].lob, imp_sth->lob[index-1].type);

    while (1) {
        if ((size = _cubrid_lob_read (imp_sth->conn, 
                                      imp_sth->lob[index-1].lob, 
                                      imp_sth->lob[index-1].type, 
                                      pos, 
                                      CUBRID_BUFFER_LEN, 
                                      buf, 
                                      &error)) < 0) {
            res = size;

dbdimp.c  view on Meta::CPAN

                                    NULL, 
                                    0, 
                                    &error)) < 0) {
            goto ER_CUBRID_FOREIGN_KEY;
        }
    }
    else if (strcmp(pk_table, "") == 0  && strcmp (fk_table, "") != 0) {
        if ((res = cci_schema_info (imp_dbh->handle, 
                                    CCI_SCH_IMPORTED_KEYS, 
                                    fk_table,
                                    NULL,
                                    0,
                                    &error)) < 0) {
            goto ER_CUBRID_FOREIGN_KEY;
        }
    }

    req_handle = res;

    if (!(col_info = cci_get_result_info (req_handle, &sql_type, &col_count))) {
        handle_error (dbh, CUBRID_ER_CANNOT_GET_COLUMN_INFO, NULL);
        return Nullsv;
    }

    rows_av = newAV ();

    if ((res = _cubrid_fetch_schema (rows_av, 
                                     req_handle, 
                                     col_count, 
                                     col_info, 
                                     &error)) < 0) {
        goto ER_CUBRID_FOREIGN_KEY;
    }

    cci_close_req_handle (req_handle);
    rows_rvav = sv_2mortal(newRV_noinc((SV *)rows_av));
    return rows_rvav;

ER_CUBRID_FOREIGN_KEY:
    cci_close_req_handle (req_handle);
    if (rows_av != Nullav) {
        av_undef(rows_av);
    }
    handle_error (dbh, res, &error);
    return Nullsv;
}

static int
_cubrid_fetch_schema( AV *rows_av, 
                      int req_handle, 
                      int col_count, 
                      T_CCI_COL_INFO *col_info, 
                      T_CCI_ERROR *error )
{
    int res;

    while (1) {
        AV *copy_row, *fetch_av;
        int i = 0;

        res = cci_cursor (req_handle, 1, CCI_CURSOR_CURRENT, error);
        if (res == CCI_ER_NO_MORE_DATA) {
            break;
        }
        else if (res < 0) {
            return res;
        }

        if ((res = cci_fetch (req_handle, error)) < 0) {
            return res;
        }

        fetch_av = newAV();
        while (i < col_count) {
            av_store (fetch_av, i, newSV(0));
            i++;
        }

        if ((res = _cubrid_fetch_row (fetch_av,
                                      req_handle, 
                                      col_count, 
                                      col_info, 
                                      error)) < 0) {

            av_undef (fetch_av);
            return res;
        }

        copy_row = av_make (AvFILL(fetch_av) + 1, AvARRAY(fetch_av));
        av_push (rows_av, newRV_noinc ((SV *)copy_row));
        
        av_undef (fetch_av);
    }

    return 0;
}

static int
_cubrid_fetch_row( AV *av, 
                   int req_handle, 
                   int col_count, 
                   T_CCI_COL_INFO *col_info, 
                   T_CCI_ERROR *error )
{
    int i, res, type, num, ind;
    char *buf;
    double ddata;

    for (i = 0; i < col_count; i++) {
        SV *sv = AvARRAY(av)[i];

        type = CCI_GET_RESULT_INFO_TYPE (col_info, i+1);
        
        switch (type) {
        case CCI_U_TYPE_INT:
        case CCI_U_TYPE_SHORT:
            if ((res = cci_get_data (req_handle, 
                            i+1, CCI_A_TYPE_INT, &num, &ind)) < 0) {
                return res;
            }



( run in 0.611 second using v1.01-cache-2.11-cpan-5837b0d9d2c )