DBD-cubrid
view release on metacpan or search on metacpan
} 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;
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;
}
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;
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 )