DBD-ODBC

 view release on metacpan or  search on metacpan

dbdimp.c  view on Meta::CPAN

            char errstr[256];

            if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 4))
                TRACE3(imp_sth, "    sql_type_case %s %"IVdf" %lx\n",  neatsvpv(sv, fbh->datalen+5), fbh->req_type, fbh->bind_flags);


            sts = DBIc_DBISTATE(imp_sth)->sql_type_cast_svpv(
                aTHX_ sv, fbh->req_type, (U32)fbh->bind_flags, NULL);

            if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 4))
                TRACE1(imp_sth, "    sql_type_cast=%d\n",  sts);

            if (sts == 0) {
                sprintf(errstr,
                        "over/under flow converting column %d to type %"IVdf"",
                        i+1, fbh->req_type);
                DBIh_SET_ERR_CHAR(sth, (imp_xxh_t*)imp_sth, Nullch, 1,
                                  errstr, Nullch, Nullch);
                return Nullav;
            }
            else if (sts == -2) {
                sprintf(errstr,
                        "unsupported bind type %"IVdf" for column %d in sql_type_cast_svpv",
                        fbh->req_type, i+1);
                DBIh_SET_ERR_CHAR(sth, (imp_xxh_t*)imp_sth, Nullch, 1,
                                  errstr, Nullch, Nullch);
                return Nullav;
            }
        }
#endif /* DBIXS_REVISION > 13590 */

    } /* end of loop through bound columns */
    return av;
}



/* /\* SHOULD BE ABLE TO DELETE BOTH OF THESE NOW AND dbd_st_rows macro in dbdimp.h *\/ */
/* int dbd_st_rows(SV *sth, imp_sth_t *imp_sth) */
/* { */
/*    return (int)imp_sth->RowCount; */
/* } */

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




int dbd_st_finish(SV *sth, imp_sth_t *imp_sth)
{
    dTHX;
    D_imp_dbh_from_sth;
    RETCODE rc;

    if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 3))
        TRACE1(imp_sth, "    dbd_st_finish(%p)\n", sth);

    /* 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_SUCCEEDED(rc)) {
            dbd_error(sth, rc, "finish/SQLFreeStmt(SQL_CLOSE)");
            return 0;
        }
        if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 6)) {
            TRACE0(imp_dbh, "    dbd_st_finish closed query:\n");
        }
    }
    DBIc_ACTIVE_off(imp_sth);
   return 1;
}



void dbd_st_destroy(SV *sth, imp_sth_t *imp_sth)
{
    dTHX;
    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->param_status_array) {
      Safefree(imp_sth->param_status_array);
      imp_sth->param_status_array = NULL;
    }
    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 != &PL_sv_undef) {
                phs_t *phs_tpl = (phs_t*)(void*)SvPVX(sv);
                sv_free(phs_tpl->sv);
                if (phs_tpl->strlen_or_ind_array) {
                    Safefree(phs_tpl->strlen_or_ind_array);
                    phs_tpl->strlen_or_ind_array = NULL;
                }
                if (phs_tpl->param_array_buf) {
                    Safefree(phs_tpl->param_array_buf);
                    phs_tpl->param_array_buf = NULL;
                }

dbdimp.c  view on Meta::CPAN

   if (retl == SQL_NO_TOTAL) {		/* unknown length!	*/
      (void)SvOK_off(bufsv);
      return 0;
   }
#endif

   SvCUR_set(bufsv, destoffset+retl);
   *SvEND(bufsv) = '\0'; /* consistent with perl sv_setpvn etc */

   if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 4))
       TRACE1(imp_sth, "    blob_read: SvCUR=%"UVuf"\n", (UV)SvCUR(bufsv));

   return 1;
}


/*======================================================================*/
/*                                                                      */
/* S_db_storeOptions                                                    */
/* =================                                                    */
/* S_db_fetchOptions                                                    */
/* =================                                                    */
/*                                                                      */
/* An array of options/attributes we support on database handles for    */
/* storing and fetching.                                                */
/*                                                                      */
/*======================================================================*/
enum paramdir { PARAM_READ = 1, PARAM_WRITE = 2, PARAM_READWRITE = 3 };
enum gettype {PARAM_TYPE_CUSTOM = 0, PARAM_TYPE_UINT, PARAM_TYPE_STR, PARAM_TYPE_BOOL};

typedef struct {
   const char *str;
   UWORD fOption;
   enum paramdir dir;
   enum gettype type;
   UDWORD atrue;
   UDWORD afalse;
} db_params;

static db_params S_db_options[] =  {
   { "AutoCommit", SQL_AUTOCOMMIT, PARAM_READWRITE, PARAM_TYPE_BOOL, SQL_AUTOCOMMIT_ON, SQL_AUTOCOMMIT_OFF },
   { "ReadOnly", SQL_ATTR_ACCESS_MODE, PARAM_READWRITE, PARAM_TYPE_BOOL, SQL_MODE_READ_ONLY, SQL_MODE_READ_WRITE},
   { "RowCacheSize", ODBC_ROWCACHESIZE, PARAM_READ, PARAM_TYPE_CUSTOM },
#if 0 /* not defined by DBI/DBD specification */
   { "TRANSACTION",
   SQL_ACCESS_MODE, PARAM_READWRITE, PARAM_TYPE_BOOL, SQL_MODE_READ_ONLY, SQL_MODE_READ_WRITE },
   { "solid_timeout", SQL_LOGIN_TIMEOUT, PARAM_READWRITE, PARAM_TYPE_UINT },
   { "ISOLATION", PARAM_READWRITE, PARAM_TYPE_UINT, SQL_TXN_ISOLATION },
#endif
   { "odbc_SQL_DBMS_NAME", SQL_DBMS_NAME, PARAM_READ, PARAM_TYPE_CUSTOM, },
   { "odbc_SQL_DRIVER_ODBC_VER", SQL_DRIVER_ODBC_VER, PARAM_READ, PARAM_TYPE_CUSTOM },
   { "odbc_SQL_ROWSET_SIZE", SQL_ROWSET_SIZE, PARAM_READWRITE, PARAM_TYPE_UINT },
   { "odbc_ignore_named_placeholders", ODBC_IGNORE_NAMED_PLACEHOLDERS, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_default_bind_type", ODBC_DEFAULT_BIND_TYPE, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_force_bind_type", ODBC_FORCE_BIND_TYPE, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_force_rebind", ODBC_FORCE_REBIND, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_async_exec", ODBC_ASYNC_EXEC, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_err_handler", ODBC_ERR_HANDLER, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_exec_direct", ODBC_EXEC_DIRECT, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_version", ODBC_VERSION, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_cursortype", ODBC_CURSORTYPE, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_query_timeout", ODBC_QUERY_TIMEOUT, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_putdata_start", ODBC_PUTDATA_START, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_column_display_size", ODBC_COLUMN_DISPLAY_SIZE, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_utf8_on", ODBC_UTF8_ON, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_has_unicode", ODBC_HAS_UNICODE, PARAM_READ, PARAM_TYPE_CUSTOM },
   { "odbc_out_connect_string", ODBC_OUTCON_STR, PARAM_READ, PARAM_TYPE_CUSTOM},
   { "odbc_describe_parameters", ODBC_DESCRIBE_PARAMETERS, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_batch_size", ODBC_BATCH_SIZE, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_array_operations", ODBC_ARRAY_OPERATIONS, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   { "odbc_taf_callback", ODBC_TAF_CALLBACK, PARAM_READWRITE, PARAM_TYPE_CUSTOM },
   {"odbc_trace", SQL_ATTR_TRACE, PARAM_READWRITE, PARAM_TYPE_BOOL, SQL_OPT_TRACE_ON, SQL_OPT_TRACE_OFF},
   {"odbc_trace_file", SQL_ATTR_TRACEFILE, PARAM_READWRITE, PARAM_TYPE_STR, },
   { NULL },
};

/*======================================================================*/
/*                                                                      */
/*  S_dbOption                                                          */
/*  ==========                                                          */
/*                                                                      */
/*  Given a string and a length, locate this option in the specified    */
/*  array of valid options. Typically used by STORE and FETCH methods   */
/*  to decide if this option/attribute is supported by us.              */
/*                                                                      */
/*======================================================================*/
static const db_params *
   S_dbOption(const db_params *pars, char *key, STRLEN len)
{
   /* search option to set */
   while (pars->str != NULL) {
      if (strncmp(pars->str, key, len) == 0
	  && len == strlen(pars->str))
	 break;
      pars++;
   }
   if (pars->str == NULL) {
      return NULL;
   }
   return pars;
}



/*======================================================================*/
/*                                                                      */
/* dbd_db_STORE_attrib                                                  */
/* ===================                                                  */
/*                                                                      */
/* This function handles:                                               */
/*                                                                      */
/*   $dbh->{$key} = $value                                              */
/*                                                                      */
/* Method to handle the setting of driver specific attributes and DBI   */
/* attributes AutoCommit and ChopBlanks (no other DBI attributes).      */
/*                                                                      */
/* Return TRUE if the attribute was handled, else FALSE.                */
/*                                                                      */
/*======================================================================*/
int dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
{

dbdimp.c  view on Meta::CPAN

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",0),        /* 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("odbc_query_timeout",0),	/* 16 */
   s_A("odbc_putdata_start",0),	/* 17 */
   s_A("ParamTypes",0),        /* 18 */
   s_A("odbc_column_display_size",0),	/* 19 */
   s_A("odbc_force_bind_type",0),             /* 20 */
   s_A("odbc_batch_size",0),	/* 21 */
   s_A("odbc_array_operations",0),	/* 22 */
   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("odbc_query_timeout",0),	/* 3 */
   s_A("odbc_putdata_start",0),	/* 4 */
   s_A("odbc_column_display_size",0),	/* 5 */
   s_A("odbc_force_bind_type",0),	/* 6 */
   s_A("odbc_batch_size",0),	/* 7 */
   s_A("odbc_array_operations",0),	/* 8 */
   s_A("",0),			/* END */
};
#undef s_A



/*======================================================================*/
/*                                                                      */
/*  dbd_st_FETCH_attrib                                                 */
/*  ===================                                                 */
/*                                                                      */
/*======================================================================*/
SV *dbd_st_FETCH_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv)
{
   dTHX;
   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,0))
   {
      /* 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.  */
       if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 4)) {
           TRACE1(imp_sth,
                  "   !!!dbd_st_FETCH_attrib (%s) needed query description, "
                  "but failed\n", par->str);
      }
      if (DBIc_WARN(imp_sth)) {
          warn("Describe failed during %s->FETCH(%s,%d)",
               SvPV(sth,PL_na), key,imp_sth->done_desc);
      }
      return &PL_sv_undef;
   }

   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_TRACE(imp_sth, DBD_TRACING, 0, 9)) {
	    TRACE1(imp_sth, "    dbd_st_FETCH_attrib NUM_OF_FIELDS %d\n", i);
        }
        retsv = newSViv(i);
        break;
      case 2: 			/* NAME */
	 av = newAV();
	 retsv = newRV_inc(sv_2mortal((SV*)av));
	 if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 9)) {
	    int j;
	    TRACE1(imp_sth, "    dbd_st_FETCH_attrib NAMES %d\n", i);

	    for (j = 0; j < i; j++)
                TRACE1(imp_sth, "\t%s\n", imp_sth->fbh[j].ColName);
	 }
	 while(--i >= 0) {
             if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 9)) {
                 TRACE2(imp_sth, "    Colname %d => %s\n",
                        i, imp_sth->fbh[i].ColName);
             }
#ifdef WITH_UNICODE
             av_store(av, i,
                      sv_newwvn(aTHX_ (SQLWCHAR *)imp_sth->fbh[i].ColName,
                                imp_sth->fbh[i].ColNameLen));
#else
             av_store(av, i, newSVpv(imp_sth->fbh[i].ColName, 0));
#endif
	 }
	 break;
      case 3:			/* NULLABLE */
	 av = newAV();
	 retsv = newRV_inc(sv_2mortal((SV*)av));
	 while(--i >= 0)
	    av_store(av, i,
		     (imp_sth->fbh[i].ColNullable == SQL_NO_NULLS)
		     ? &PL_sv_no : &PL_sv_yes);
	 break;
      case 4:			/* TYPE */
	 av = newAV();
	 retsv = newRV_inc(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_inc(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_inc(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_inc(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_inc(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_SUCCEEDED(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);
	 if (i == 0 && imp_sth->moreResults == 0) {
	    int outparams = (imp_sth->out_params_av) ?
                AvFILL(imp_sth->out_params_av)+1 : 0;
	    if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 4)) {
                TRACE0(imp_sth,
                       "    numfields == 0 && moreResults = 0 finish\n");
	    }
	    if (outparams) {
	       odbc_handle_outparams(aTHX_ imp_sth, DBIc_TRACE_LEVEL(imp_sth));
	    }
        imp_sth->done_desc = 0;                 /* redo describe */

	       /* XXX need to 'finish' here */
	    dbd_st_finish(sth, imp_sth);
	 } else {
             if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 4)) {
                 TRACE2(imp_sth,
                        "    fetch odbc_more_results, numfields == %d "
                        "&& moreResults = %d\n", i, imp_sth->moreResults);
             }
         }
	 break;
      case 11:                                  /* ParamValues */
      {
	 /* 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 != &PL_sv_undef) {
		  phs_t *phs = (phs_t*)(void*)SvPVX(sv);
		  (void)hv_store(paramvalues, phs->name, (I32)strlen(phs->name),
                         newSVsv(phs->sv), 0);
	       }
	    }
	 }
	 /* ensure HV is freed when the ref is freed */
	 retsv = newRV_noinc((SV *)paramvalues);
         break;
      }
      case 12: /* LongReadLen */
	 retsv = newSViv(DBIc_LongReadLen(imp_sth));
	 break;
      case 13: /* odbc_ignore_named_placeholders */
	 retsv = newSViv(imp_sth->odbc_ignore_named_placeholders);
	 break;
      case 14: /* odbc_default_bind_type */
	 retsv = newSViv(imp_sth->odbc_default_bind_type);
	 break;
      case 15: /* odbc_force_rebind */
	 retsv = newSViv(imp_sth->odbc_force_rebind);
	 break;
      case 16: /* odbc_query_timeout */

dbdimp.c  view on Meta::CPAN

        (PK_CatalogName && *PK_CatalogName) ? PK_CatalogName : 0, SQL_NTS,
        (PK_SchemaName && *PK_SchemaName) ? PK_SchemaName : 0, SQL_NTS,
        (PK_TableName && *PK_TableName) ? PK_TableName : 0, SQL_NTS,
        (FK_CatalogName && *FK_CatalogName) ? FK_CatalogName : 0, SQL_NTS,
        (FK_SchemaName && *FK_SchemaName) ? FK_SchemaName : 0, SQL_NTS,
        (FK_TableName && *FK_TableName) ? FK_TableName : 0, SQL_NTS);
    if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 4))
        TRACE1(imp_dbh, "    SQLForeignKeys=%d\n", rc);

    if (!SQL_SUCCEEDED(rc)) {
        dbd_error(sth, rc, "odbc_get_foreign_keys/SQLForeignKeys");
        return 0;
    }
    return build_results(aTHX_ sth, imp_sth, dbh, imp_dbh, rc);
}



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



int odbc_get_type_info(
    SV *dbh,
    SV *sth,
    int ftype)
{
   dTHX;
   D_imp_dbh(dbh);
   D_imp_sth(sth);
   RETCODE rc;
   int dbh_active;
   size_t max_stmt_len;

#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 ((dbh_active = check_connection_active(aTHX_ dbh)) == 0) return 0;

   rc = SQLAllocHandle(SQL_HANDLE_STMT, imp_dbh->hdbc, &imp_sth->hstmt);
   if (rc != SQL_SUCCESS) {
      dbd_error(sth, rc, "odbc_get_type_info/SQLAllocHandle(stmt)");
      return 0;
   }

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

#ifdef WITH_UNICODE
   rc = SQLGetTypeInfoW(imp_sth->hstmt, (SQLSMALLINT)ftype);
#else
   rc = SQLGetTypeInfo(imp_sth->hstmt, (SQLSMALLINT)ftype);
#endif
   if (DBIc_TRACE(imp_sth, DBD_TRACING, 0, 4))
       TRACE2(imp_dbh, "    SQLGetTypeInfo(%d)=%d\n", ftype, rc);

   dbd_error(sth, rc, "odbc_get_type_info/SQLGetTypeInfo");
   if (!SQL_SUCCEEDED(rc)) {
      SQLFreeHandle(SQL_HANDLE_STMT,imp_sth->hstmt);
      imp_sth->hstmt = SQL_NULL_HSTMT;
      return 0;
   }

   return build_results(aTHX_ sth, imp_sth, dbh, imp_dbh, rc);
}



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

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



IV odbc_st_lob_read(
    SV *sth,
    int colno,

dbdimp.c  view on Meta::CPAN


}



/************************************************************************/
/*                                                                      */
/*  set_odbc_version                                                    */
/*  ================                                                    */
/*                                                                      */
/*  Set the ODBC version we require. This defaults to ODBC 3 but if     */
/*  attr contains the odbc_version atttribute this overrides it. If we  */
/*  fail for any reason the env handle is freed, the error reported and */
/*  0 is returned. If all ok, 1 is returned.                            */
/*                                                                      */
/************************************************************************/
static int set_odbc_version(
    pTHX_
    SV *dbh,
    imp_dbh_t *imp_dbh,
    SV* attr)
{
    D_imp_drh_from_dbh;
    SV **svp;
    UV odbc_version = 0;
    SQLRETURN rc;


    DBD_ATTRIB_GET_IV(
        attr, "odbc_version", 12, svp, odbc_version);
    if (svp && odbc_version) {
        rc = SQLSetEnvAttr(imp_drh->henv, SQL_ATTR_ODBC_VERSION,
                           (SQLPOINTER)odbc_version, SQL_IS_INTEGER);
    } else {
        /* make sure we request a 3.0 version */
        rc = SQLSetEnvAttr(imp_drh->henv, SQL_ATTR_ODBC_VERSION,
                           (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
    }
    if (!SQL_SUCCEEDED(rc)) {
        dbd_error2(
            dbh, rc, "db_login/SQLSetEnvAttr", imp_drh->henv, 0, 0);
        if (imp_drh->connects == 0) {
            SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
            imp_drh->henv = SQL_NULL_HENV;
        }
        return 0;
    }
    return 1;
}



/*
 *  post_connect
 *  ==========
 *
 *  Operations to perform immediately after we have connected.
 *
 *  NOTE: prior to DBI subversion version 11605 (fixed post 1.607)
 *    DBD_ATTRIB_DELETE segfaulted so instead of calling:
 *    DBD_ATTRIB_DELETE(attr, "odbc_cursortype",
 *                      strlen("odbc_cursortype"));
 *    we do the following:
 *      hv_delete((HV*)SvRV(attr), "odbc_cursortype",
 *                strlen("odbc_cursortype"), G_DISCARD);
 */

static int post_connect(
    pTHX_
    SV *dbh,
    imp_dbh_t *imp_dbh,
    SV *attr)
{
    D_imp_drh_from_dbh;
    SQLRETURN rc;
    SWORD dbvlen;
    UWORD supported;

    /* default this now before we may change it below */
    imp_dbh->switch_to_longvarchar = ODBC_SWITCH_TO_LONGVARCHAR;

    if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
        TRACE0(imp_dbh, "Turning autocommit on\n");

    /* DBI spec requires AutoCommit on */
    rc = SQLSetConnectAttr(imp_dbh->hdbc, SQL_AUTOCOMMIT,
                           (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
    if (!SQL_SUCCEEDED(rc)) {
        dbd_error(dbh, rc, "post_connect/SQLSetConnectAttr(SQL_AUTOCOMMIT)");
        SQLFreeHandle(SQL_HANDLE_DBC, imp_dbh->hdbc);
        if (imp_drh->connects == 0) {
            SQLFreeHandle(SQL_HANDLE_ENV, imp_drh->henv);
            imp_drh->henv = SQL_NULL_HENV;
            imp_dbh->henv = SQL_NULL_HENV;    /* needed for dbd_error */
        }
        return 0;
    }
    DBIc_set(imp_dbh,DBIcf_AutoCommit, 1);

    /* get the ODBC compatibility level for this driver */
    rc = SQLGetInfo(imp_dbh->hdbc, SQL_DRIVER_ODBC_VER, &imp_dbh->odbc_ver,
                    (SWORD)sizeof(imp_dbh->odbc_ver), &dbvlen);
    if (!SQL_SUCCEEDED(rc)) {
        dbd_error(dbh, rc, "post_connect/SQLGetInfo(DRIVER_ODBC_VER)");
        strcpy(imp_dbh->odbc_ver, "01.00");
    }
    if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
        TRACE1(imp_dbh, "DRIVER_ODBC_VER = %s\n", imp_dbh->odbc_ver);

    /* get ODBC driver name and version */
    rc = SQLGetInfo(imp_dbh->hdbc, SQL_DRIVER_NAME, &imp_dbh->odbc_driver_name,
                    (SQLSMALLINT)sizeof(imp_dbh->odbc_driver_name), &dbvlen);
    if (!SQL_SUCCEEDED(rc)) {
        dbd_error(dbh, rc, "post_connect/SQLGetInfo(DRIVER_NAME)");
        strcpy(imp_dbh->odbc_driver_name, "unknown");
        imp_dbh->driver_type = DT_DONT_CARE;
    } else {
        if (strcmp(imp_dbh->odbc_driver_name, "SQLSRV32.DLL") == 0) {
            imp_dbh->driver_type = DT_SQL_SERVER;
        } else if ((strcmp(imp_dbh->odbc_driver_name, "sqlncli10.dll") == 0) ||
                   (strcmp(imp_dbh->odbc_driver_name, "SQLNCLI.DLL") == 0) ||
                   (memcmp(imp_dbh->odbc_driver_name, "libmsodbcsql", 13) == 0)) {
            imp_dbh->driver_type = DT_SQL_SERVER_NATIVE_CLIENT;
        } else if (strcmp(imp_dbh->odbc_driver_name, "odbcjt32.dll") == 0) {
            imp_dbh->driver_type = DT_MS_ACCESS_JET;

dbdimp.c  view on Meta::CPAN

    /* flag to see if SQLDescribeParam is supported */
    imp_dbh->odbc_sqlmoreresults_supported = -1;
    imp_dbh->odbc_defer_binding = 0;
    imp_dbh->odbc_force_rebind = 0;
    /* default value for query timeout is -1 which means do not set the
       query timeout at all. */
    imp_dbh->odbc_query_timeout = -1;
    imp_dbh->odbc_putdata_start = 32768;
    imp_dbh->odbc_batch_size = 10;
    imp_dbh->read_only = -1;                    /* show not set yet */

    /*printf("odbc_batch_size defaulted to %d\n", imp_dbh->odbc_batch_size);*/
    imp_dbh->odbc_column_display_size = 2001;
    imp_dbh->odbc_utf8_on = 0;
    imp_dbh->odbc_exec_direct = 0; /* default to not having SQLExecDirect used */
    imp_dbh->odbc_describe_parameters = 1;
    imp_dbh->RowCacheSize = 1;	/* default value for now */

#ifdef WE_DONT_DO_THIS_ANYMORE
    if (!strcmp(imp_dbh->odbc_dbms_name, "Microsoft SQL Server")) {
        if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
            TRACE0(imp_dbh, "Deferring Binding\n");
        imp_dbh->odbc_defer_binding = 1;
    }
#endif

    /* check to see if SQLMoreResults is supported */
    rc = SQLGetFunctions(imp_dbh->hdbc, SQL_API_SQLMORERESULTS, &supported);
    if (SQL_SUCCEEDED(rc)) {
        if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
            TRACE1(imp_dbh, "SQLMoreResults supported: %d\n", supported);
        imp_dbh->odbc_sqlmoreresults_supported = supported ? 1 : 0;
    } else {
        imp_dbh->odbc_sqlmoreresults_supported = 0;
        if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
            TRACE0(imp_dbh,
                   "    !!SQLGetFunctions(SQL_API_SQLMORERESULTS) failed:\n");
        AllODBCErrors(imp_dbh->henv, imp_dbh->hdbc, 0,
                      DBIc_TRACE(imp_dbh, DBD_TRACING, 0, 3), DBIc_LOGPIO(imp_dbh));
    }

    /* call only once per connection / DBH -- may want to do
     * this during the connect to avoid potential threading
     * issues */
    /* check to see if SQLDescribeParam is supported */
    rc = SQLGetFunctions(imp_dbh->hdbc, SQL_API_SQLDESCRIBEPARAM, &supported);
    if (SQL_SUCCEEDED(rc)) {
        if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
            TRACE1(imp_dbh, "SQLDescribeParam supported: %d\n", supported);
        imp_dbh->odbc_sqldescribeparam_supported = supported ? 1 : 0;
    } else {
        imp_dbh->odbc_sqldescribeparam_supported = 0;
        if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
            TRACE0(imp_dbh,
                   "    !!SQLGetFunctions(SQL_API_SQLDESCRIBEPARAM) failed:\n");
        AllODBCErrors(imp_dbh->henv, imp_dbh->hdbc, 0,
                      DBIc_TRACE(imp_dbh, DBD_TRACING, 0, 3),
                      DBIc_LOGPIO(imp_dbh));
    }

    /* odbc_cursortype */
    {
        SV **svp;
        UV odbc_cursortype = 0;

        DBD_ATTRIB_GET_IV(attr, "odbc_cursortype", 15,
                          svp, odbc_cursortype);
        if (svp && odbc_cursortype) {
            if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
                TRACE1(imp_dbh,
                       "    Setting cursor type to: %"UVuf"\n", odbc_cursortype);
            /* delete odbc_cursortype so we don't see it again via STORE */
            (void)hv_delete((HV*)SvRV(attr), "odbc_cursortype",
                            strlen("odbc_cursortype"), G_DISCARD);

            rc = SQLSetConnectAttr(imp_dbh->hdbc,(SQLINTEGER)SQL_CURSOR_TYPE,
                                   (SQLPOINTER)odbc_cursortype,
                                   (SQLINTEGER)SQL_IS_INTEGER);
            if (!SQL_SUCCEEDED(rc) && (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0)))
                TRACE1(imp_dbh, "    !!Failed to set SQL_CURSORTYPE to %d\n",
                       (int)odbc_cursortype);
        }
    }

    /* odbc_query_timeout */
    {
        SV **svp;
        UV   odbc_timeout = 0;

        DBD_ATTRIB_GET_IV(
            attr, "odbc_query_timeout", strlen("odbc_query_timeout"),
            svp, odbc_timeout);
        if (svp && odbc_timeout) {
            imp_dbh->odbc_query_timeout = odbc_timeout;
            if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
                TRACE1(imp_dbh, "    Setting DBH query timeout to %d\n",
                       (int)odbc_timeout);
            /* delete odbc_cursortype so we don't see it again via STORE */
            (void)hv_delete((HV*)SvRV(attr), "odbc_query_timeout",
                            strlen("odbc_query_timeout"), G_DISCARD);
        }
    }

    /* odbc_putdata_start */
    {
        SV **svp;
        IV putdata_start_value;

        DBD_ATTRIB_GET_IV(
            attr, "odbc_putdata_start", strlen("odbc_putdata_start"),
            svp, putdata_start_value);
        if (svp) {
            imp_dbh->odbc_putdata_start = putdata_start_value;
            if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
                TRACE1(imp_dbh, "    Setting DBH putdata_start to %d\n",
                       (int)putdata_start_value);
            /* delete odbc_putdata_start so we don't see it again via STORE */
            (void)hv_delete((HV*)SvRV(attr), "odbc_putdata_start",
                            strlen("odbc_putdata_start"), G_DISCARD);
        }
    }

    /* odbc_column_display_size */
    {
        SV **svp;
        IV column_display_size_value;

        DBD_ATTRIB_GET_IV(
            attr, "odbc_column_display_size",
            strlen("odbc_column_display_size"),
            svp, column_display_size_value);
        if (svp) {
            imp_dbh->odbc_column_display_size = column_display_size_value;
            if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
                TRACE1(imp_dbh,
                       "    Setting DBH default column display size to %d\n",
                       (int)column_display_size_value);
            /* delete odbc_column_display_size so we don't see it again via STORE */
            (void)hv_delete((HV*)SvRV(attr), "odbc_column_display_size",
                            strlen("odbc_column_display_size"), G_DISCARD);
        }
    }

    /* odbc_utf8_on */
    {
        SV **svp;
        IV utf8_on_value;

        DBD_ATTRIB_GET_IV(
            attr, "odbc_utf8_on",
            strlen("odbc_utf8_on"),
            svp, utf8_on_value);
        if (svp) {
            imp_dbh->odbc_utf8_on = utf8_on_value;
            if (DBIc_TRACE(imp_dbh, CONNECTION_TRACING, 0, 0))
                TRACE1(imp_dbh,
                       "    Setting UTF8_ON to %d\n",
                       (int)utf8_on_value);



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