DBD-DB2

 view release on metacpan or  search on metacpan

dbdimp.c  view on Meta::CPAN

	 	croak( "Error: Modification of a read-only value attempted" );
    	if( !SvOK( bufsv) )
	 	sv_setpv( bufsv, "" ); /* initialize undefined variable */
    	SvGROW( bufsv, (STRLEN)(destoffset + len + cbNullSize) );
	
    	rtval = SQLGetData( imp_sth->phstmt,
			(SQLUSMALLINT) field,
			fbh->ftype,
			SvPVX(bufsv) + destoffset,
			len + cbNullSize,
			&retl );
	
    	if (rtval == SQL_SUCCESS_WITH_INFO)      /* XXX should check for 01004 */
	 	retl = len;
	
    	if (retl == SQL_NULL_DATA)      /* field is null    */
    	{
	 	(void)SvOK_off(bufsv);
	 	return TRUE;
    	}
	
	CHECK_ERROR(sth, SQL_HANDLE_STMT, imp_sth->phstmt, rtval, "GetData Failed To Read LOB");
    	EOI(rtval);
	
    	SvCUR_set(bufsv, destoffset+retl );
    	*SvEND(bufsv) = '\0'; /* consistent with perl sv_setpvn etc    */
	
    	return TRUE;
}

int dbd_st_rows( SV *sth,
		imp_sth_t *imp_sth ) {

	return imp_sth->RowCount;
}

int dbd_st_cancel( SV *sth,
		imp_sth_t *imp_sth ) {
    
	D_imp_dbh_from_sth;
    	SQLRETURN ret;
	
    	if (DBIc_ACTIVE(imp_sth) ) {
		ret = SQLCancel(imp_sth->phstmt);
		CHECK_ERROR(sth, SQL_HANDLE_STMT, imp_sth->phstmt, ret, "SQLCancel Failed");
		EOI(ret);
		
		ret = SQLFreeStmt(imp_sth->phstmt,SQL_CLOSE);
		CHECK_ERROR(sth, SQL_HANDLE_STMT, imp_sth->phstmt, ret, "SQLCancel Failed");
		EOI(ret);
    	}
    	DBIc_ACTIVE_off(imp_sth);
    	return TRUE;
}

int dbd_st_finish( SV *sth,
		imp_sth_t *imp_sth ) {

	D_imp_dbh_from_sth;
    	SQLRETURN ret;
    	/* Cancel further fetches from this cursor.  We don't        */
    	/* close the cursor (SQLFreeHandle) 'til DESTROY (dbd_st_destroy).*/
    	/* The application may call execute(...) again on the same   */
    	/* statement handle.                                         */
	
    	if (DBIc_ACTIVE(imp_sth) ) {
		ret = SQLFreeStmt(imp_sth->phstmt,SQL_CLOSE);
		CHECK_ERROR(sth, SQL_HANDLE_STMT, imp_sth->phstmt, ret, "SQLFreeStmt Failed");
		EOI(ret);
    	}
    	DBIc_ACTIVE_off(imp_sth);
    	return TRUE;
}

void dbd_st_destroy( SV *sth,
		imp_sth_t *imp_sth ) {
    
	D_imp_dbh_from_sth;
    	SQLINTEGER i;
	SQLRETURN ret;
	
    	/* Free off contents of imp_sth    */
	
    	for( i = 0; i < imp_sth->numFieldsAllocated; ++i) {
	  	imp_fbh_t *fbh = &imp_sth->fbh[i];
	  	Safefree( fbh->buffer );
    	}
    	Safefree(imp_sth->fbh);
    	Safefree(imp_sth->fbh_cbuf);
    	Safefree(imp_sth->statement);
	
    	if (imp_sth->bind_names) {
	  	HV *hv = imp_sth->bind_names;
	  	SV *sv;
	  	char *key;
	  	I32 retlen;
	  	phs_t *phs;
		
	  	hv_iterinit(hv);
	  	while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) {
			if (sv != &PL_sv_undef) {
		      		phs = (phs_t*)SvPVX(sv);
		      		SvREFCNT_dec( phs->sv );
		      		if( phs->buffer != NULL && phs->bufferSize > 0 )
			   		Safefree( phs->buffer );
			}
	  	}
	  	sv_free((SV*)imp_sth->bind_names);
    	}
	
    	if( DBIc_ACTIVE( imp_dbh ) &&
			!DBIc_IADESTROY( imp_sth ) &&
			SQL_NULL_HSTMT != imp_sth->phstmt ) {
	  	ret = SQLFreeHandle( SQL_HANDLE_STMT, imp_sth->phstmt );
		CHECK_ERROR(sth, SQL_HANDLE_STMT, imp_sth->phstmt, ret, "Statement Destruction Error");
	  	imp_sth->phstmt = SQL_NULL_HSTMT;
    	}
    	DBIc_IMPSET_off( imp_sth );  /* let DBI know we've done it */
}

static SQLINTEGER getStatementAttr( char *key,
		STRLEN keylen ) {
      	/* For better performance, the keys are sorted by length */
      	switch( keylen )
      	{
#ifndef AS400
	    	case 10:
		  	if(      strEQ( key, "db2_noscan" ) )
				return SQL_ATTR_NOSCAN;
		  	return SQL_ERROR;
			
	    	case 12:
		  	if(      strEQ( key, "db2_max_rows" ) )
				return SQL_ATTR_MAX_ROWS;
		  	else if( strEQ( key, "db2_prefetch" ) )
				return SQL_ATTR_PREFETCH;
		  	return SQL_ERROR;
			
	    	case 14:
		  	if(      strEQ( key, "db2_earlyclose" ) )
				return SQL_ATTR_EARLYCLOSE;
		  	else if( strEQ( key, "db2_max_length" ) )
				return SQL_ATTR_MAX_LENGTH;
		  	else if( strEQ( key, "db2_row_number" ) )
				return SQL_ATTR_ROW_NUMBER;
		  	return SQL_ERROR;
#endif
			
	    	case 15:
			if(      strEQ( key, "db2_call_return" ) )
				return SQL_ATTR_CALL_RETURN;
			else if( strEQ( key, "db2_concurrency" ) )
				return SQL_ATTR_CONCURRENCY;
		  	else if( strEQ( key, "db2_cursor_hold" ) )
				return SQL_ATTR_CURSOR_HOLD;
		  	return SQL_ERROR;
			
#ifndef AS400
	    	case 17:
		  	if(      strEQ( key, "db2_query_timeout" ) )
				return SQL_ATTR_QUERY_TIMEOUT;
		  	else if( strEQ( key, "db2_retrieve_data" ) )
				return SQL_ATTR_RETRIEVE_DATA;
		  	else if( strEQ( key, "db2_txn_isolation" ) )
				return SQL_ATTR_TXN_ISOLATION;
		  	return SQL_ERROR;
			
	    	case 20:
		  	if(      strEQ( key, "db2_deferred_prepare" ) )
				return SQL_ATTR_DEFERRED_PREPARE;
		  	return SQL_ERROR;
#endif
		case 21:
			if(      strEQ( key, "db2_rowcount_prefetch") )
				return SQL_ATTR_ROWCOUNT_PREFETCH;
			return SQL_ERROR;
			
	    	case 22:
		  	if(      strEQ( key, "db2_optimize_for_nrows" ) )
				return SQL_ATTR_OPTIMIZE_FOR_NROWS;
		  	return SQL_ERROR;
			
	    	case 28:
		  	if(      strEQ( key, "db2_query_optimization_level" ) )
				return SQL_ATTR_QUERY_OPTIMIZATION_LEVEL;
		  	return SQL_ERROR;
			
	    	default:
		  	return SQL_ERROR;
      	}
}

int dbd_st_STORE_attrib( SV *sth,
		imp_sth_t *imp_sth,
		SV *keysv,
		SV *valuesv ) {
      
	STRLEN kl;
      	char *key = SvPV( keysv, kl );
      	SQLINTEGER Attribute = getStatementAttr( key, kl );
      	SQLRETURN ret;
      	SQLPOINTER ValuePtr = 0;
      	SQLINTEGER StringLength = 0;
      	char msg[128]; /* buffer for error messages */
#ifdef AS400
      	SQLPOINTER param;
#endif
	
      	if( Attribute < 0 ) /* Don't know what this attribute is */
	    	return FALSE;
	
      	switch( Attribute ) {
	    	/* Booleans */
#ifndef AS400

dbdimp.c  view on Meta::CPAN

		CHECK_ERROR(sth, SQL_HANDLE_STMT, imp_sth->phstmt, ret, msg);
	    	return FALSE;
      	}
	
      	return TRUE;
}

SV *dbd_st_FETCH_attrib( SV *sth,
		imp_sth_t *imp_sth,
		SV *keysv ) {
      
	STRLEN kl;
      	char *key = SvPV( keysv, kl ); 
      	int i;
      	SV *retsv = NULL;
      	AV *av;
      	int cacheit = 1;
      	SQLINTEGER Attribute;
      	SQLRETURN ret = 0;
	
      	if (!imp_sth->done_desc && !dbd_describe(sth, imp_sth)) {
	    	/* dbd_describe has already called check_error()        */
	    	/* We can't return Nullsv here because the xs code will */
	    	/* then just pass the attribute name to DBI for FETCH.  */
	    	croak("Describe failed during %s->FETCH(%s)",
		     		SvPV(sth,PL_na), key);
      	}
	
      	i = DBIc_NUM_FIELDS(imp_sth);
	
      	if( kl == 7 && strEQ( key, "lengths" ) ) {
	    	av = newAV();
	    	retsv = sv_2mortal( newRV_inc( (SV*)av ) );
	    	while(--i >= 0)
			av_store(av, i, newSViv((IV)imp_sth->fbh[i].dsize));
      	}
      	else if( kl == 5 && strEQ( key, "types" ) ) {
	    	av = newAV();
	    	retsv = sv_2mortal( newRV_inc( (SV*)av ) );
	    	while(--i >= 0)
			av_store(av, i, newSViv(imp_sth->fbh[i].dbtype));
      	}
      	else if( kl == 13 && strEQ( key, "NUM_OF_PARAMS" ) ) {
	    	HV *bn = imp_sth->bind_names;
	    	retsv = sv_2mortal( newSViv( (bn) ? HvKEYS(bn) : 0 ) );
      	}
      	else if( kl == 4 && strEQ( key, "NAME" ) ) {
	    	av = newAV();
	    	retsv = sv_2mortal( newRV_inc( sv_2mortal((SV*)av) ) );
	    	while(--i >= 0)
			av_store(av, i, newSVpv((char *)imp_sth->fbh[i].cbuf,0));
      	}
      	else if( kl == 8 && strEQ( key, "NULLABLE" ) ) {
	    	av = newAV();
	    	retsv = sv_2mortal( newRV_inc( sv_2mortal((SV*)av) ) );
	    	while(--i >= 0)
			av_store(av, i,
		       			(imp_sth->fbh[i].nullok == 1) ? &PL_sv_yes : &PL_sv_no);
      	}
      	else if( kl == 10 && strEQ( key, "CursorName" ) ) {
	    	char cursor_name[256];
	    	SQLSMALLINT cursor_name_len;
	    	ret = SQLGetCursorName(imp_sth->phstmt, (SQLCHAR *)cursor_name,
     				sizeof(cursor_name), &cursor_name_len);
		CHECK_ERROR(sth, SQL_HANDLE_STMT, imp_sth->phstmt, ret, "SQLNGetCursorName Failed");
	    	if (ret < 0)
			return Nullsv;
	    	else
			retsv = sv_2mortal( newSVpv(cursor_name, cursor_name_len) );
      	}
      	else if( kl == 4 && strEQ( key, "TYPE" ) ) {
	    	av = newAV();
	    	retsv = sv_2mortal( newRV_inc( sv_2mortal( (SV*)av ) ) );
	    	while(--i >= 0)
			av_store(av, i, newSViv(imp_sth->fbh[i].dbtype));
      	}
      	else if( kl == 9 && strEQ( key, "PRECISION" ) ) {
	    	av = newAV();
	    	retsv = sv_2mortal( newRV_inc( sv_2mortal( (SV*)av ) ) );
	    	while(--i >= 0)
			av_store(av, i, newSViv(imp_sth->fbh[i].prec));
      	}
      	else if( kl == 5 && strEQ( key, "SCALE" ) ) {
	    	av = newAV();
	    	retsv = sv_2mortal( newRV_inc( sv_2mortal( (SV*)av ) ) );
	    	while(--i >= 0)
			av_store(av, i, newSViv(imp_sth->fbh[i].scale));
      	}
      	else if( 16 == kl && strEQ( key, "db2_more_results" ) ) {
	    	if( !DBIc_ACTIVE(imp_sth) ) {
		  	/* Statement has been finished, no more results available */
		  	retsv = &PL_sv_no;
	    	}
	    	else if( imp_sth->bMoreResults ) {
		  	/* Already know that there are more result sets */
		  	retsv = &PL_sv_yes;
	    	}
	    	else {
		  	ret = SQLMoreResults( imp_sth->phstmt );
			CHECK_ERROR(sth, SQL_HANDLE_STMT, imp_sth->phstmt, ret, "Error Getting More Results");
		  	if( SQL_SUCCESS == ret ) {
				retsv = &PL_sv_yes;
		  	}
		  	else {
				/* No more results, finish statement */
				dbd_st_finish(sth, imp_sth);
				retsv = &PL_sv_no;
		  	}
	    	}
		
	    	if( &PL_sv_yes == retsv ) {
		  	/* describe and allocate storage for results        */
		  	imp_sth->done_desc = FALSE;
			
		  	/* Remove statement attribs in cache                */
		  	if (hv_exists((HV*) SvRV(sth), "NAME", 4) )
		       		hv_delete((HV *) SvRV(sth), "NAME", 4, G_DISCARD);
			
		  	if (hv_exists((HV*) SvRV(sth), "NAME_uc", 7))
		       		hv_delete((HV *) SvRV(sth), "NAME_uc", 7, G_DISCARD);
			
		  	if (hv_exists((HV*) SvRV(sth), "NAME_lc", 7) )
		       		hv_delete((HV *) SvRV(sth), "NAME_lc", 7, G_DISCARD);
			
		  	if (hv_exists((HV*) SvRV(sth), "TYPE", 4) )
		       		hv_delete((HV *) SvRV(sth), "TYPE", 4, G_DISCARD);
			
		  	if (hv_exists((HV*) SvRV(sth), "PRECISION", 9) )
		       		hv_delete((HV *) SvRV(sth), "PRECISION", 9, G_DISCARD);



( run in 0.816 second using v1.01-cache-2.11-cpan-39bf76dae61 )