DBD-Mimer

 view release on metacpan or  search on metacpan

dbdimp.c  view on Meta::CPAN

	     */
	    char *p = name;
	    *dest++ = '?';

	    while(isALNUM(*src))	/* includes '_'	*/
		*p++ = *src++;
	    *p = 0;
	    if (DBIc_DEBUGIV(imp_sth) >= 5)
		PerlIO_printf(DBIc_LOGPIO(imp_sth), "    found named parameter = %s\n",
			      name);
	    style = 2;
	} 
	else {			/* perhaps ':=' PL/SQL construct */
	    *dest++ = ch;
	    continue;
	}
	*dest = '\0';			/* handy for debugging	*/
	if (laststyle && style != laststyle)
	    croak("Can't mix placeholder styles (%d/%d)",style,laststyle);
	laststyle = style;

	if (imp_sth->all_params_hv == NULL)
	    imp_sth->all_params_hv = newHV();
	namelen = strlen(name);

	svpp = hv_fetch(imp_sth->all_params_hv, name, namelen, 0);
	if (svpp == NULL) {
	    /* create SV holding the placeholder */
	    phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)+namelen+1);
	    phs = (phs_t*)SvPVX(phs_sv);
	    strcpy(phs->name, name);
	    phs->idx = idx;

	    /* store placeholder to all_params_hv */
	    svpp = hv_store(imp_sth->all_params_hv, name, namelen, phs_sv, 0);
	}
    }
    *dest = '\0';
    if (imp_sth->all_params_hv) {
	DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv);
	if (DBIc_DEBUGIV(imp_sth) >= 2)
	    PerlIO_printf(DBIc_LOGPIO(imp_sth), "    dbd_preparse scanned %d distinct placeholders\n",
			  (int)DBIc_NUM_PARAMS(imp_sth));
    }
}


int
dbd_st_tables(dbh, sth, catalog, schema, table, table_type)
SV *dbh;
SV *sth;
char *catalog;
char *schema;
char *table;
char *table_type;
{
    D_imp_dbh(dbh);
    D_imp_sth(sth);
    RETCODE rc;
    /* SV **svp; */
    /* char cname[128];	*/				/* cursorname */
    dTHR;

    imp_sth->henv = imp_dbh->henv;	/* needed for dbd_error */
    imp_sth->hdbc = imp_dbh->hdbc;

    imp_sth->done_desc = 0;

    if (!DBIc_ACTIVE(imp_dbh)) {
	dbd_error(sth, SQL_ERROR, "Can not allocate statement when disconnected from the database");
	return 0;
    }

    rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);/* TBD: 3.0 update */
    if (rc != SQL_SUCCESS) {
	dbd_error(sth, rc, "st_tables/SQLAllocStmt");
	return 0;
    }

    /* just for sanity, later.  Any internals that may rely on this (including */
    /* debugging) will have valid data */
    imp_sth->statement = (char *)safemalloc(strlen(cSqlTables)+
					    strlen(XXSAFECHAR(catalog)) +
					    strlen(XXSAFECHAR(schema)) +
					    strlen(XXSAFECHAR(table)) +
					    strlen(XXSAFECHAR(table_type))+1);
    sprintf(imp_sth->statement, cSqlTables, XXSAFECHAR(catalog),
	    XXSAFECHAR(schema), XXSAFECHAR(table), XXSAFECHAR(table_type));

    rc = SQLTables(imp_sth->hstmt,
		   (catalog && *catalog) ? catalog : 0, SQL_NTS,
		   (schema && *schema) ? schema : 0, SQL_NTS,
		   (table && *table) ? table : 0, SQL_NTS,
		   table_type && *table_type ? table_type : 0, SQL_NTS		/* type (view, table, etc) */
		  );

    if (DBIc_DEBUGIV(imp_sth) >= 2)
	PerlIO_printf(DBIc_LOGPIO(imp_dbh), "   Tables result %d (%s)\n",
		      rc, table_type ? table_type : "(null)");

    dbd_error(sth, rc, "st_tables/SQLTables");
    if (!SQL_ok(rc)) {
        SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
	/* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
	imp_sth->hstmt = SQL_NULL_HSTMT;
	return 0;
    }

    return build_results(sth,rc);
}

int
dbd_st_primary_keys(dbh, sth, catalog, schema, table)
SV *dbh;
SV *sth;
char *catalog;
char *schema;
char *table;
{
   dTHR;
   D_imp_dbh(dbh);

dbdimp.c  view on Meta::CPAN


   imp_sth->henv = imp_dbh->henv;	/* needed for dbd_error */
   imp_sth->hdbc = imp_dbh->hdbc;
    
   imp_sth->done_desc = 0;

   if (!DBIc_ACTIVE(imp_dbh)) {
       dbd_error(sth, SQL_ERROR, "Can not allocate statement when disconnected from the database");
       return 0;
   }

   rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);/* TBD: 3.0 update */
   if (rc != SQL_SUCCESS) {
      dbd_error(sth, rc, "odbc_db_primary_key_info/SQLAllocStmt");
      return 0;
   }
    
   /* just for sanity, later.  Any internals that may rely on this (including */
   /* debugging) will have valid data */
   imp_sth->statement = (char *)safemalloc(strlen(cSqlPrimaryKeys)+
					   strlen(XXSAFECHAR(catalog))+
					   strlen(XXSAFECHAR(schema))+
					   strlen(XXSAFECHAR(table))+1);
    
   sprintf(imp_sth->statement,
	   cSqlPrimaryKeys, XXSAFECHAR(catalog), XXSAFECHAR(schema),
	   XXSAFECHAR(table));
   
   rc = SQLPrimaryKeys(imp_sth->hstmt,
		       (catalog && *catalog) ? catalog : 0, SQL_NTS,
		       (schema && *schema) ? schema : 0, SQL_NTS,
		       (table && *table) ? table : 0, SQL_NTS);
   
   if (DBIc_DEBUGIV(imp_sth) >= 2)
      PerlIO_printf(DBIc_LOGPIO(imp_dbh), "SQLPrimaryKeys call: cat = %s, schema = %s, table = %s\n",
		    XXSAFECHAR(catalog), XXSAFECHAR(schema), XXSAFECHAR(table));

   dbd_error(sth, rc, "st_primary_key_info/SQLPrimaryKeys");
    
   if (!SQL_ok(rc)) {
      SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
      /* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
      imp_sth->hstmt = SQL_NULL_HSTMT;
      return 0;
   }

   return build_results(sth,rc);
}

int
   dbd_st_prepare(sth, imp_sth, statement, attribs)
   SV *sth;
imp_sth_t *imp_sth;
char *statement;
SV *attribs;
{
    dTHR;
    D_imp_dbh_from_sth;
    RETCODE rc;
    /* SV **svp;
    char cname[128]; */		/* cursorname */

    imp_sth->done_desc = 0;
    imp_sth->henv = imp_dbh->henv;	/* needed for dbd_error */
    imp_sth->hdbc = imp_dbh->hdbc;
    imp_sth->odbc_ignore_named_placeholders = imp_dbh->odbc_ignore_named_placeholders;
    imp_sth->odbc_default_bind_type = imp_dbh->odbc_default_bind_type;
    imp_sth->odbc_force_rebind = imp_dbh->odbc_force_rebind;

    if (!DBIc_ACTIVE(imp_dbh)) {
	dbd_error(sth, 0, "Can not allocate statement when disconnected from the database");
    }

    if (!DBIc_ACTIVE(imp_dbh)) {
	dbd_error(sth, SQL_ERROR, "Can not allocate statement when disconnected from the database");
	return 0;
    }

    rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);/* TBD: 3.0 update */
    if (!SQL_ok(rc)) {
	dbd_error(sth, rc, "st_prepare/SQLAllocStmt");
	return 0;
    }

    imp_sth->odbc_exec_direct = imp_dbh->odbc_exec_direct;

    {
       /*
        * allow setting of odbc_execdirect in prepare() or overriding
        */
       SV **odbc_exec_direct_sv;
       /* if the attribute is there, let it override what the default
        * value from the dbh is (set above).
        */
       if ((odbc_exec_direct_sv = DBD_ATTRIB_GET_SVP(attribs, "odbc_execdirect", 10)) != NULL) {
	  imp_sth->odbc_exec_direct = SvIV(*odbc_exec_direct_sv) != 0;
       }
    }
    /* scan statement for '?', ':1' and/or ':foo' style placeholders	*/
    dbd_preparse(imp_sth, statement);

    /* Hold this statement for subsequent call of dbd_execute */
    if (!imp_sth->odbc_exec_direct) {
       /* parse the (possibly edited) SQL statement */
       rc = SQLPrepare(imp_sth->hstmt, 
		       imp_sth->statement, strlen(imp_sth->statement));
       if (DBIc_DEBUGIV(imp_sth) >= 2)
	  PerlIO_printf(DBIc_LOGPIO(imp_dbh), "    SQLPrepare returned %d\n\n",
			rc);

       if (!SQL_ok(rc)) {
	  dbd_error(sth, rc, "st_prepare/SQLPrepare");
	  SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
	  /* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
	  imp_sth->hstmt = SQL_NULL_HSTMT;
	  return 0;
       }
    }
    if (DBIc_DEBUGIV(imp_sth) >= 2)
	PerlIO_printf(DBIc_LOGPIO(imp_dbh), "    dbd_st_prepare'd sql f%d, ExecDirect=%d\n\t%s\n",
		      imp_sth->hstmt, imp_sth->odbc_exec_direct, imp_sth->statement);

dbdimp.c  view on Meta::CPAN

		 * Since we've detected the problem locally via the datalen,
		 * we don't need to worry about the value of rc.
		 * 
		 * This used to make sure rc was set to SQL_SUCCESS_WITH_INFO 
		 * but since it's an error and not SUCCESS, call dbd_error() 
		 * with SQL_ERROR explicitly instead.
		 */

		dbd_error(sth, SQL_ERROR, "st_fetch/SQLFetch (long truncated DBI attribute LongTruncOk not set and/or LongReadLen too small)");
		return Nullav;
	    }
	    /* LongTruncOk true, just ensure perl has the right length
	     * for the truncated data.
	     */
	    sv_setpvn(sv, (char*)fbh->data, fbh->ColDisplaySize);
	}
	else switch(fbh->ftype) {
#ifdef TIMESTAMP_STRUCT /* iODBC doesn't define this */
	    TIMESTAMP_STRUCT *ts;
	    case SQL_C_TIMESTAMP:
	    case SQL_C_TYPE_TIMESTAMP:
		ts = (TIMESTAMP_STRUCT *)fbh->data;
		sprintf(cvbuf, "%04d-%02d-%02d %02d:%02d:%02d",
			ts->year, ts->month, ts->day, 
			ts->hour, ts->minute, ts->second, ts->fraction);
		sv_setpv(sv, cvbuf);
		break;
#endif
	    default:
		if (ChopBlanks && fbh->ColSqlType == SQL_CHAR && fbh->datalen > 0) {
		    char *p = (char*)fbh->data;
		    while(fbh->datalen && p[fbh->datalen - 1]==' ')
			--fbh->datalen;
		}
		sv_setpvn(sv, (char*)fbh->data, fbh->datalen);
	}
    }
    return av;
}


int
   dbd_st_rows(sth, imp_sth)
   SV *sth;
imp_sth_t *imp_sth;
{
    return imp_sth->RowCount;
}


int
   dbd_st_finish(sth, imp_sth)
   SV *sth;
imp_sth_t *imp_sth;
{
    dTHR;
    D_imp_dbh_from_sth;
    RETCODE rc;
    int ret = 0;

    /* Cancel further fetches from this cursor.                 */
    /* We don't close the cursor till DESTROY (dbd_st_destroy). */
    /* The application may re execute(...) it.                  */

    /* XXX semantics of finish (eg oracle vs odbc) need lots more thought */
    /* re-read latest DBI specs and ODBC manuals */
    if (DBIc_ACTIVE(imp_sth) && imp_dbh->hdbc != SQL_NULL_HDBC) {

	rc = SQLFreeStmt(imp_sth->hstmt, SQL_CLOSE);/* TBD: 3.0 update */
	if (!SQL_ok(rc)) {
	    dbd_error(sth, rc, "finish/SQLFreeStmt(SQL_CLOSE)");
	    return 0;
	}
	if (DBIc_DEBUGIV(imp_sth) > 5) {
	   PerlIO_printf(DBIc_LOGPIO(imp_dbh), "dbd_st_finish closed query:\n");
	}
    }
    DBIc_ACTIVE_off(imp_sth);
    return 1;
}


void
   dbd_st_destroy(sth, imp_sth)
   SV *sth;
imp_sth_t *imp_sth;
{
    dTHR;
    D_imp_dbh_from_sth;
    RETCODE rc;

    /* Free contents of imp_sth	*/

    /* PerlIO_printf(DBIc_LOGPIO(imp_dbh), "  dbd_st_destroy\n"); */
    Safefree(imp_sth->fbh);
    Safefree(imp_sth->RowBuffer);
    Safefree(imp_sth->ColNames);
    Safefree(imp_sth->statement);

    if (imp_sth->out_params_av)
	sv_free((SV*)imp_sth->out_params_av);

    if (imp_sth->all_params_hv) {
	HV *hv = imp_sth->all_params_hv;
	SV *sv;
	char *key;
	I32 retlen;
	hv_iterinit(hv);
	while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) {
	    if (sv != &sv_undef) {
		phs_t *phs_tpl = (phs_t*)(void*)SvPVX(sv);
		sv_free(phs_tpl->sv);
	    }
	}
	sv_free((SV*)imp_sth->all_params_hv);
    }

    /* SQLxxx functions dump core when no connection exists. This happens
     * when the db was disconnected before perl ending.  Hence,
     * checking for the dirty flag.
     */
    if (imp_dbh->hdbc != SQL_NULL_HDBC && !dirty) {

dbdimp.c  view on Meta::CPAN

 * the result set to operate, hence don't do a describe unless you need
 * to do one.
 * DBD::ODBC 0.45_15
 * */
typedef struct {
    const char *str;
    unsigned len:8;
    unsigned array:1;
    unsigned need_describe:1;
    unsigned filler:22;
} T_st_params;

#define s_A(str,need_describe) { str, sizeof(str)-1,0,need_describe }
static T_st_params S_st_fetch_params[] = 
{
    s_A("NUM_OF_PARAMS",1),	/* 0 */
    s_A("NUM_OF_FIELDS",1),	/* 1 */
    s_A("NAME",1),		/* 2 */
    s_A("NULLABLE",1),		/* 3 */
    s_A("TYPE",1),		/* 4 */
    s_A("PRECISION",1),		/* 5 */
    s_A("SCALE",1),		/* 6 */
    s_A("sol_type",1),		/* 7 */
    s_A("sol_length",1),	/* 8 */
    s_A("CursorName",1),		/* 9 */
    s_A("odbc_more_results",1),	/* 10 */
    s_A("ParamValues",1),		/* 11 */

    s_A("LongReadLen",0),		/* 12 */
    s_A("odbc_ignore_named_placeholders",0),	/* 13 */
    s_A("odbc_default_bind_type",0),	/* 14 */
    s_A("odbc_force_rebind",0),	/* 15 */
    s_A("",0),			/* END */
};

static T_st_params S_st_store_params[] = 
{
   s_A("odbc_ignore_named_placeholders",0),	/* 0 */
   s_A("odbc_default_bind_type",0),	/* 1 */
   s_A("odbc_force_rebind",0),	/* 2 */
   s_A("",0),			/* END */
};
#undef s_A

/*----------------------------------------
 * dummy routines st_XXXX
 *----------------------------------------
 */
SV *
   dbd_st_FETCH_attrib(sth, imp_sth, keysv)
   SV *sth;
imp_sth_t *imp_sth;
SV *keysv;
{
    dTHR;
    STRLEN kl;
    char *key = SvPV(keysv,kl);
    int i;
    SV *retsv = NULL;
    T_st_params *par;
    char cursor_name[256];
    SWORD cursor_name_len;
    RETCODE rc;

    for (par = S_st_fetch_params; par->len > 0; par++)
	if (par->len == kl && strEQ(key, par->str))
	    break;

    if (par->len <= 0)
	return Nullsv;

    if (par->need_describe && !imp_sth->done_desc && !dbd_describe(sth, imp_sth)) 
    {
	/* dbd_describe has already called dbd_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,na), key);
    }

    i = DBIc_NUM_FIELDS(imp_sth);

    switch(par - S_st_fetch_params)
    {
	AV *av;

	case 0:			/* NUM_OF_PARAMS */
	    return Nullsv;	/* handled by DBI */
	case 1:			/* NUM_OF_FIELDS */
	   if (DBIc_DEBUGIV(imp_sth) > 8) {
	      PerlIO_printf(DBIc_LOGPIO(imp_sth), " dbd_st_FETCH_attrib NUM_OF_FIELDS %d\n", i);
	   }
	    retsv = newSViv(i);
	    break;
	case 2: 			/* NAME */
	    av = newAV();
	    retsv = newRV(sv_2mortal((SV*)av));
	    if (DBIc_DEBUGIV(imp_sth) > 8) {
	       int j;
	       PerlIO_printf(DBIc_LOGPIO(imp_sth), " dbd_st_FETCH_attrib NAMES %d\n", i);

	       for (j = 0; j < i; j++) {
		  PerlIO_printf(DBIc_LOGPIO(imp_sth), "\t%s\n", imp_sth->fbh[j].ColName);
		  PerlIO_flush(DBIc_LOGPIO(imp_sth));
	       }
	       PerlIO_flush(DBIc_LOGPIO(imp_sth));
	    }
	    while(--i >= 0) {
	       if (DBIc_DEBUGIV(imp_sth) > 8) {
		  PerlIO_printf(DBIc_LOGPIO(imp_sth), "    Colname %d => %s\n",
				i, imp_sth->fbh[i].ColName);
		  PerlIO_flush(DBIc_LOGPIO(imp_sth));
	       }
		av_store(av, i, newSVpv(imp_sth->fbh[i].ColName, 0));
	    }
	    break;
	case 3:			/* NULLABLE */
	    av = newAV();
	    retsv = newRV(sv_2mortal((SV*)av));
	    while(--i >= 0)
		av_store(av, i,
			 (imp_sth->fbh[i].ColNullable == SQL_NO_NULLS)
			 ? &sv_no : &sv_yes);
	    break;
	case 4:			/* TYPE */
	    av = newAV();
	    retsv = newRV(sv_2mortal((SV*)av));
	    while(--i >= 0) 
		av_store(av, i, newSViv(imp_sth->fbh[i].ColSqlType));
	    break;
	case 5:			/* PRECISION */
	    av = newAV();
	    retsv = newRV(sv_2mortal((SV*)av));
	    while(--i >= 0) 
		av_store(av, i, newSViv(imp_sth->fbh[i].ColDef));
	    break;
	case 6:			/* SCALE */
	    av = newAV();
	    retsv = newRV(sv_2mortal((SV*)av));
	    while(--i >= 0) 
		av_store(av, i, newSViv(imp_sth->fbh[i].ColScale));
	    break;
	case 7:			/* sol_type */
	    av = newAV();
	    retsv = newRV(sv_2mortal((SV*)av));
	    while(--i >= 0) 
		av_store(av, i, newSViv(imp_sth->fbh[i].ColSqlType));
	    break;
	case 8:			/* sol_length */
	    av = newAV();
	    retsv = newRV(sv_2mortal((SV*)av));
	    while(--i >= 0) 
		av_store(av, i, newSViv(imp_sth->fbh[i].ColLength));
	    break;
	case 9:			/* CursorName */
	    rc = SQLGetCursorName(imp_sth->hstmt,
				  cursor_name, sizeof(cursor_name), &cursor_name_len);
	    if (!SQL_ok(rc)) {
		dbd_error(sth, rc, "st_FETCH/SQLGetCursorName");
		return Nullsv;
	    }
	    retsv = newSVpv(cursor_name, cursor_name_len);
	    break;
	case 10:                /* odbc_more_results */
	    retsv = newSViv(imp_sth->moreResults);
	    break;
	case 11:
	{
	   /* not sure if there's a memory leak here. */
	   HV *paramvalues = newHV();
	   if (imp_sth->all_params_hv) {
	      HV *hv = imp_sth->all_params_hv;
	      SV *sv;
	      char *key;
	      I32 retlen;
	      hv_iterinit(hv);
	      while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) {
		 if (sv != &sv_undef) {
		    phs_t *phs = (phs_t*)(void*)SvPVX(sv);
		    hv_store(paramvalues, phs->name, strlen(phs->name), newSVsv(phs->sv), 0);
		 }
	      }
	   }
	   /* ensure HV is freed when the ref is freed */
	   retsv = newRV_noinc((SV *)paramvalues);
	}
	break;
	case 12:
	    retsv = newSViv(DBIc_LongReadLen(imp_sth));
	    break;
	case 13:
	    retsv = newSViv(imp_sth->odbc_ignore_named_placeholders);
	    break;
	case 14:
	   retsv = newSViv(imp_sth->odbc_default_bind_type);
	   break;
	case 15: /* force rebind */
	   retsv = newSViv(imp_sth->odbc_force_rebind);
	   break;
	default:
	    return Nullsv;
    }

    return sv_2mortal(retsv);
}


int
   dbd_st_STORE_attrib(sth, imp_sth, keysv, valuesv)
   SV *sth;
imp_sth_t *imp_sth;
SV *keysv;
SV *valuesv;
{
    dTHR;
    D_imp_dbh_from_sth;
    STRLEN kl;
    STRLEN vl;
    char *key = SvPV(keysv,kl);
    char *value = SvPV(valuesv, vl);
    T_st_params *par;

dbdimp.c  view on Meta::CPAN


    rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);/* TBD: 3.0 update */
    if (rc != SQL_SUCCESS) {
	dbd_error(sth, rc, "odbc_get_foreign_keys/SQLAllocStmt");
	return 0;
    }

    rc = SQLForeignKeys(imp_sth->hstmt, 
			PK_CatalogName, strlen(PK_CatalogName), 
			PK_SchemaName, strlen(PK_SchemaName), 
			PK_TableName, strlen(PK_TableName), 
			FK_CatalogName, strlen(FK_CatalogName), 
			FK_SchemaName, strlen(FK_SchemaName), 
			FK_TableName, strlen(FK_TableName));
    if (!SQL_ok(rc)) {
	dbd_error(sth, rc, "odbc_get_foreign_keys/SQLForeignKeys");
	return 0;
    }
    return build_results(sth,rc);
}


int
   odbc_describe_col(sth, colno, ColumnName, BufferLength, NameLength, DataType, ColumnSize, DecimalDigits, Nullable)
   SV *sth;
int colno;
char *ColumnName;
I16 BufferLength;
I16 *NameLength;
I16 *DataType;
U32 *ColumnSize;
I16 *DecimalDigits;
I16 *Nullable;
{
    D_imp_sth(sth);
    SQLUINTEGER ColSize;
    RETCODE rc;
    rc = SQLDescribeCol(imp_sth->hstmt, colno,
			ColumnName, BufferLength, NameLength,
			DataType, &ColSize, DecimalDigits, Nullable);
    if (!SQL_ok(rc)) {
	dbd_error(sth, rc, "DescribeCol/SQLDescribeCol");
	return 0;
    }
	*ColumnSize = ColSize;
    return 1;
}


int
   odbc_get_type_info(dbh, sth, ftype)
   SV *dbh;
SV *sth;
int ftype;
{
    dTHR;
    D_imp_dbh(dbh);
    D_imp_sth(sth);
    RETCODE rc;
#if 0
    /* TBD: cursorname? */
    char cname[128];			/* cursorname */
#endif

    imp_sth->henv = imp_dbh->henv;	/* needed for dbd_error */
    imp_sth->hdbc = imp_dbh->hdbc;

    imp_sth->done_desc = 0;

    if (!DBIc_ACTIVE(imp_dbh)) {
	dbd_error(sth, SQL_ERROR, "Can not allocate statement when disconnected from the database");
	return 0;
    }

    rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);/* TBD: 3.0 update */
    if (rc != SQL_SUCCESS) {
	dbd_error(sth, rc, "odbc_get_type_info/SQLGetTypeInfo");
	return 0;
    }

    /* just for sanity, later. Any internals that may rely on this (including */
    /* debugging) will have valid data */
    imp_sth->statement = (char *)safemalloc(strlen(cSqlGetTypeInfo)+ftype/10+1);
    sprintf(imp_sth->statement, cSqlGetTypeInfo, ftype);

    rc = SQLGetTypeInfo(imp_sth->hstmt, ftype);

    dbd_error(sth, rc, "odbc_get_type_info/SQLGetTypeInfo");
    if (!SQL_ok(rc)) {
        SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
	/* SQLFreeStmt(imp_sth->hstmt, SQL_DROP);*/ /* TBD: 3.0 update */
	imp_sth->hstmt = SQL_NULL_HSTMT;
	return 0;
    }

    return build_results(sth,rc);
}


SV *
   odbc_cancel(sth)
   SV *sth;
{
    dTHR;
    D_imp_sth(sth);
    RETCODE rc;

    if ( !DBIc_ACTIVE(imp_sth) ) {
	dbd_error(sth, SQL_ERROR, "no statement executing");
	return Nullsv;
    }

    rc = SQLCancel(imp_sth->hstmt);
    if (!SQL_ok(rc)) {
	dbd_error(sth, rc, "odbc_cancel/SQLCancel");
	return Nullsv;
    }
    return newSViv(1);
}


SV *



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