DBD-Solid

 view release on metacpan or  search on metacpan

dbdimp.c  view on Meta::CPAN

         *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->params_hv == NULL )
         imp_sth->params_hv = newHV();

      namelen = strlen( name );
      svpp = hv_fetch( imp_sth->params_hv, name, namelen, 0 );

      if( svpp == NULL )
         {
         /* create SV holding the placeholder  */
         phs_tpl.sv = &sv_undef;
         phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)+namelen+1);
         strcpy( ((phs_t*)SvPVX(phs_sv))->name, name);

         /* store placeholder to params_hv */
         svpp = hv_store( imp_sth->params_hv, name, namelen, phs_sv, 0 );
         }

      svref = newRV( *svpp );

      /* store reference to placeholder to params_av */
      if( imp_sth->params_av == NULL )
         imp_sth->params_av = newAV();
      
      av_push( imp_sth->params_av, svref );

      } /* end while(*src) */

   *dest = '\0';

   if (imp_sth->params_hv)
      {
      DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->params_hv);
	
      if (dbis->debug >= 2)
         fprintf(DBILOGFP, "    dbd_preparse scanned %d distinct placeholders\n",
                 (int)DBIc_NUM_PARAMS(imp_sth));
      }

   }

/* --------------------------------------------------------
* Prepare SQL statement.  Relies on dbd_preparse.
* --------------------------------------------------------- */
int dbd_st_prepare( SV* sth, char* statement, SV* attribs )
   {
   D_imp_sth(sth);
   D_imp_dbh_from_sth;
   RETCODE rc;
   dTHR;
   SV** svp;
   char cname[128];    /* cursorname */

   imp_sth->done_desc = 0;

   /* Deprecated as of ODBC 3.x.  --mms */
   /*rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);
   solid_error(sth, rc, "st_prepare/SQLAllocStmt"); */

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

   /* scan statement for '?', ':1' and/or ':foo' style placeholders	*/
   dbd_preparse( imp_sth, statement );

   /* parse the (possibly edited) SQL statement */
   rc = SQLPrepare( imp_sth->hstmt, 
                    imp_sth->statement,
                    strlen(imp_sth->statement));
   solid_error( sth, rc, "st_prepare/SQLPrepare" );

   if( rc != SQL_SUCCESS )
      {
      /* SQLFreeStmt is deprecated only with option SQL_DROP. --mms
      SQLFreeStmt(imp_sth->hstmt, SQL_DROP); */
      SQLFreeHandle( SQL_HANDLE_STMT, imp_sth->hstmt );
      
      imp_sth->hstmt = SQL_NULL_HSTMT;
      return 0;
      }

#if 0 /* use DBIc macros */
   imp_sth->long_buflen   = 80;  /* typical  default	*/
   imp_sth->long_trunc_ok = 0;   /* can use blob_read()		*/
#endif 
    
   if( dbis->debug >= 2 )
      fprintf(DBILOGFP, "    dbd_st_prepare'd sql f%d\n\t%s\n",
              imp_sth->hstmt, imp_sth->statement);

   /* init sth pointers */
   imp_sth->fbh = NULL;
   imp_sth->ColNames = NULL;
   imp_sth->RowBuffer = NULL;
   imp_sth->n_result_cols = -1;
   imp_sth->RowCount = -1;
   imp_sth->eod = -1;

   /* @@@ DBI Bug ??? */
   DBIc_set( imp_sth, DBIcf_LongTruncOk,
             DBIc_is(imp_dbh, DBIcf_LongTruncOk) );
   
   DBIc_LongReadLen(imp_sth) = DBIc_LongReadLen(imp_dbh);

   sprintf( cname, "dbd_cursor_%X", imp_sth->hstmt );
   rc = SQLSetCursorName( imp_sth->hstmt, cname, strlen(cname) );

   if( rc != SQL_SUCCESS )
      warn("dbd_prepare: can't set cursor name, rc = %d", rc);

   if( dbis->debug >= 2 )
	fprintf(DBILOGFP, "    CursorName is '%s', rc=%d\n", cname, rc);

   if( attribs )
      {
      if( (svp=hv_fetch((HV*)SvRV(attribs), "blob_size",9, 0)) != NULL )
         {
         int len = SvIV( *svp );
         DBIc_LongReadLen( imp_sth ) = len;
         if( DBIc_WARN(imp_sth) )
            warn("deprecated feature: blob_size will be replaced by LongReadLen\n");
         }
      
      if( (svp=hv_fetch((HV*)SvRV(attribs), "solid_blob_size",15, 0)) != NULL )
         {
         int len = SvIV(*svp);
         DBIc_LongReadLen(imp_sth) = len;
         if( DBIc_WARN(imp_sth) )
            warn("deprecated feature: solid_blob_size will be replaced by LongReadLen\n");
         }

      if( (svp=hv_fetch((HV*)SvRV(attribs), "LongReadLen",11, 0)) != NULL )
         {
         int len = SvIV(*svp);
         DBIc_LongReadLen(imp_sth) = len;
         }
	
#if YET_NOT_IMPLEMENTED
      if( (svp=hv_fetch((HV*)SvRV(attribs), "concurrency",11, 0)) != NULL )
         {
         UDWORD param = SvIV( *svp );
         rc = SQLSetStmtOption( imp_sth->hstmt, SQL_CONCURRENCY, param );
         if( rc != SQL_SUCCESS )
            warn("prepare: can't set concurrency, rc = %d", rc);
         }
#endif
      }

   /* Call dbd_describe if this named constant is non-zero */
#if DESCRIBE_IN_PREPARE
   if( dbis->debug >= 2 )
      fprintf(DBILOGFP, "Describe in prepare: %d\n", DESCRIBE_IN_PREPARE);
      
   if( dbd_describe(sth, imp_sth) <= 0 )
      return 0;
#endif

   DBIc_IMPSET_on( imp_sth );

   return 1;
   }

/* -----------------------------------------
*  Returns 1 if arg is string, 0 otherwise.
* ------------------------------------------ */
int dbtype_is_string( int bind_type )
   {
   switch( bind_type )
      {

dbdimp.c  view on Meta::CPAN

                  sv_setpv(sv, cvbuf);
               break;
              
               default:
                  if( dbis->debug >= 2 )
                    fprintf(DBILOGFP, "dbd_st_fetch colsqltype: %d\tlength: %d\n",
                           fbh->ColSqlType, fbh->datalen); 
                  
                  if( fbh->ColSqlType == SQL_CHAR
                        && DBIc_is(imp_sth, DBIcf_ChopBlanks)
                        && fbh->datalen > 0 )
                     {                       
                     int len = fbh->datalen;
                     char* p0  = (char*)(fbh->data);
                     char* p   = (char*)(fbh->data) + len;
                     
                     if( dbis->debug >= 2 )
                        fprintf(DBILOGFP, "dbd_st_fetch: got to here\n");
                     
                     while( p-- != p0 )
                        {
                        if( *p != ' ' )
                           break;
                        
                        len--;   
                        }
                     sv_setpvn(sv, p0, len);
                     break;
                     }
                              
                  if( dbis->debug >= 2 )
                     fprintf( DBILOGFP, "dbd_st_fetch  string: %s  length: %d\n",
                              fbh->data, fbh->datalen );
                              
                  sv_setpvn(sv, (char*)fbh->data, fbh->datalen);
               break;
   		      }
            }
         }
      else
         {
         SvOK_off(sv);
         }
      }  /* end for */

   return av;
   }

/* -------------------------------
* 
* -------------------------------- */
int dbd_st_finish( SV* sth )
   {
   D_imp_sth( sth );
   D_imp_dbh_from_sth;
   D_imp_drh_from_dbh;
   RETCODE rc;
   dTHR;
   int ret = 1;

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

   if( DBIc_ACTIVE(imp_sth) && imp_dbh->hdbc != SQL_NULL_HDBC )
      {
      rc = SQLFreeStmt( imp_sth->hstmt, SQL_CLOSE );
      solid_error( sth, rc, "st_finish/SQLFreeStmt(SQL_CLOSE)" );

      if( rc != SQL_SUCCESS )
         ret = 0;

#ifdef SOL22_AUTOCOMMIT_BUG
      if( DBIc_is(imp_dbh, DBIcf_AutoCommit) )
         {
         
         /* Deprecated as of ODBC 3.x. --mms
         rc = SQLTransact(imp_drh->henv, imp_dbh->hdbc, SQL_COMMIT); */
         
         rc = SQLEndTran( SQL_HANDLE_DBC, imp_dbh->hdbc, SQL_COMMIT );
         }
#endif
      }
   DBIc_ACTIVE_off( imp_sth );

   return ret;
   }

/* -----------------------------------------
* 
* ------------------------------------------ */
void dbd_st_destroy( SV* sth )
   {
   D_imp_sth( sth );
   D_imp_dbh_from_sth;
   D_imp_drh_from_dbh;
   RETCODE rc;
   dTHR;

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

      /* This is deprecated when used with option SQL_DROP --mms */
      rc = SQLFreeStmt( imp_sth->hstmt, SQL_DROP );
      
      /* But its replacement does weird things.  --mms
      SQLFreeHandle(SQL_HANDLE_STMT, imp_sth->hstmt);*/
      
      if( rc != SQL_SUCCESS )
         {
         warn("warning: DBD::Solid SQLFreeStmt returns %d\n", rc);
         }
      }

   /* Free contents of imp_sth	*/
   Safefree( imp_sth->fbh );
   Safefree( imp_sth->ColNames );
   Safefree( imp_sth->RowBuffer );
   Safefree( imp_sth->statement );

dbdimp.c  view on Meta::CPAN


      case SQL_OPT_TRACEFILE:
         retsv = newSVpv((char*)vParam, 0);
      break;

      default:
         if( vParam == pars->true )
            retsv = newSViv(1);
         else
            retsv = newSViv(0);
      break;
      }

   return sv_2mortal( retsv );
   }

#define s_A(str) { str, sizeof(str)-1 }
static T_st_params S_st_fetch_params[] = 
   {
   s_A("NUM_OF_PARAMS"),      /* 0 */
   s_A("NUM_OF_FIELDS"),      /* 1 */
   s_A("NAME"),               /* 2 */
   s_A("NULLABLE"),           /* 3 */
   s_A("TYPE"),               /* 4 */
   s_A("PRECISION"),          /* 5 */
   s_A("SCALE"),              /* 6 */
   s_A("sol_type"),           /* 7 */
   s_A("sol_length"),         /* 8 */
   s_A("CursorName"),         /* 9 */
   s_A("blob_size"),          /* 10 */
   s_A("__handled_by_dbi__"), /* 11 */ /* ChopBlanks */
   s_A("solid_blob_size"),    /* 12 */
   s_A("solid_type"),         /* 13 */
   s_A("solid_length"),       /* 14 */
   s_A("LongReadLen"),        /* 15 */
   s_A(""),                   /* END */
   };

static T_st_params S_st_store_params[] = 
   {
   s_A("blob_size"),       /* 0 */
   s_A("solid_blob_size"), /* 1 */
   s_A(""),                /* END */
   };
#undef s_A

/*----------------------------------------
* dummy routines st_XXXX
*---------------------------------------- */
SV* dbd_st_FETCH( SV* sth, SV* keysv )
   {
   D_imp_sth( sth );
   STRLEN kl;
   dTHR;
   char* key = SvPV(keysv,kl);
   int i;
   SV* retsv = NULL;
   T_st_params* par;
   int n_fields;
   imp_fbh_t* fbh;
   char cursor_name[256];
   SWORD cursor_name_len;
   RETCODE rc;
   int par_index;

   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( !imp_sth->done_desc && !dbd_describe(sth, imp_sth) )
      {
      /* dbd_describe has already called ora_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_index = par - S_st_fetch_params )
      {
      AV* av;

      case 0:     /* NUM_OF_PARAMS */
         return Nullsv;	/* handled by DBI */

      case 1:     /* NUM_OF_FIELDS */
         retsv = newSViv(i);
      break;

      case 2:     /* NAME */
         av = newAV();
         retsv = newRV(sv_2mortal((SV*)av));
         while(--i >= 0)
            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 )
            {
            switch( imp_sth->fbh[i].ColNullable )
               {
               case SQL_NULLABLE:
                  av_store(av, i, &sv_yes);
               break;
               
               case SQL_NO_NULLS:
                  av_store(av, i, &sv_no);
               break;

               case SQL_NULLABLE_UNKNOWN:
                  av_store(av, i, &sv_undef);
               break;
               }
            }
      break;

      case 4:     /* TYPE */
         av = newAV();
         retsv = newRV(sv_2mortal((SV*)av));
         while( --i >= 0 )
            {
            int type = imp_sth->fbh[i].ColSqlType;
            av_store(av, i, newSViv(type));
            }
      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:     /* dbd_type */
         if( DBIc_WARN(imp_sth) )
            warn("Depreciated feature 'sol_type'. "
                 "Please use 'solid_type' instead.");
      
      /* fall through */
      case 13:    /* solid_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:     /* dbd_length */
         if( DBIc_WARN(imp_sth) )
            warn("Depreciated feature 'sol_length'. "
                 "Please use 'solid_length' instead.");

      /* fall through */
      case 14:    /* solid_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);
      
         solid_error( sth, rc, "st_FETCH/SQLGetCursorName" );
      
         if( rc != SQL_SUCCESS )
            {
            if( dbis->debug >= 1 )
               {
               fprintf(DBILOGFP,
                  "SQLGetCursorName returned %d in dbd_st_FETCH\n", rc);
               }
            return Nullsv;
            }
         retsv = newSVpv( cursor_name, cursor_name_len );
      break;

      case 10:    /* blob_size */
         if( DBIc_WARN(imp_sth) )
            warn("Depreciated feature 'blob_size'. "
                 "Please use 'solid_blob_size' instead.");

      /* fall through */
      case 12:    /* solid_blob_size */
      case 15:    /* LongReadLen */
         retsv = newSViv(DBIc_LongReadLen(imp_sth));
      break;

      default:
         return Nullsv;
      }

   return sv_2mortal( retsv );
   }

/* ----------------------------------------- 
* 
* ------------------------------------------ */
int dbd_st_STORE( SV* sth, SV* keysv, SV* valuesv )
   {
   D_imp_sth( sth );
   D_imp_dbh_from_sth;
   dTHR;
   STRLEN kl;
   STRLEN vl;
   char* key = SvPV( keysv, kl );
   char* value = SvPV( valuesv, vl );
   T_st_params* par;
   RETCODE rc;
 
   for( par = S_st_store_params; par->len > 0; par++ )
      if( par->len == kl && strEQ(key, par->str) )
         break;

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

      switch( par - S_st_store_params )
         {
         case 0:     /* blob_size */
         case 1:     /* solid_blob_size */
#if DESCRIBE_IN_PREPARE
            warn("$sth->{blob_size} isn't longer supported.\n"
                 "You may either use the 'LongReadLen' "
                 "attribute to prepare()\nor the blob_read() "
                 "function.\n");
            return FALSE;
#endif
            DBIc_LongReadLen(imp_sth) = SvIV(valuesv);
            return TRUE;
         }

   return FALSE;
   }



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