DBD-DBMaker

 view release on metacpan or  search on metacpan

dbdimp.c  view on Meta::CPAN

		*p++ = *src++;
	    *p = 0;
	    style = 1;
	} 
	else if (isALNUM(*src)) {       /* ':foo'	*/
	    char *p = name;
	    idx++;                      /* #006 */
	    *dest++ = '?';

	    while(isALNUM(*src))	/* includes '_'	*/
		*p++ = *src++;
	    *p = 0;
	    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->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_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 params_hv */
	    svpp = hv_store(imp_sth->params_hv, name, namelen, phs_sv, 0);
	}
    }
    *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));
    }
}


int
dbd_st_table_info(dbh, sth, qualifier, table_type)
    SV *dbh;
    SV *sth;
    char *qualifier;
    char *table_type;
{
    D_imp_dbh(dbh);
    D_imp_sth(sth);
    RETCODE rc;
    SV **svp;
    char cname[128];				/* cursorname */

    imp_sth->done_desc = 0;
    rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);
    dbmaker_error(sth, rc, "st_tables/SQLAllocStmt");
    if (rc != SQL_SUCCESS) {
	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("SQLTables(%s)")+strlen(qualifier)+1);
    sprintf(imp_sth->statement, "SQLTables(%s)", qualifier);

    if (dbis->debug >= 2)
	fprintf(DBILOGFP, "    dbd_st_tables type = %s\n", table_type);

    rc = SQLTables(imp_sth->hstmt,
	   0, SQL_NTS,			/* qualifier */
	   0, SQL_NTS,			/* schema/user */
	   0, SQL_NTS,			/* table name */
	   table_type, SQL_NTS	/* type (view, table, etc) */
    );
    
    dbmaker_error(sth, rc, "st_tables/SQLTables");
    if (!SQL_ok(rc)) {
	SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
	imp_sth->hstmt = SQL_NULL_HSTMT;
	return 0;
    }

    /* init sth pointers */
    imp_sth->fbh = NULL;
    imp_sth->ColNames = NULL;
    imp_sth->RowBuffer = NULL;
    imp_sth->RowCount = -1;
    imp_sth->eod = -1;
#if DBMAKER_FILE_INOUT    /* #004 */  
    imp_sth->fgfileinput = 1;
    imp_sth->fgBindColToFile = 0;
#else
    imp_sth->fgfileinput = 0;
    imp_sth->fgBindColToFile = 0; 
#endif    

    if (!dbd_describe(sth, imp_sth))
    {
	    SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
	    imp_sth->hstmt = SQL_NULL_HSTMT;
	    return 0; 		/* dbd_describe already called ora_error() */
    }

    if (dbd_describe(sth, imp_sth) <= 0)
	return 0;

    DBIc_IMPSET_on(imp_sth);

    imp_sth->RowCount = -1;
    rc = SQLRowCount(imp_sth->hstmt, &imp_sth->RowCount);
    dbmaker_error(sth, rc, "st_tables/SQLRowCount");
    if (rc != SQL_SUCCESS) {
	return -1;
    }

    DBIc_ACTIVE_on(imp_sth); /* XXX should only set for select ?	*/
    imp_sth->eod = SQL_SUCCESS;
    return 1;
}

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

    imp_sth->done_desc = 0;

    rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);
    dbmaker_error(sth, rc, "st_prepare/SQLAllocStmt");
    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));
    dbmaker_error(sth, rc, "st_prepare/SQLPrepare");
    if (rc != SQL_SUCCESS)
        {
	SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
	imp_sth->hstmt = SQL_NULL_HSTMT;
	return 0;
	}

    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;
#if DBMAKER_FILE_INOUT    /* #004 */  
    imp_sth->fgfileinput = 1;
    imp_sth->fgBindColToFile = 0;
#else
    imp_sth->fgfileinput = 0;
    imp_sth->fgBindColToFile = 0; 
#endif    

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

    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("depreciated feature: blob_size will be replaced by LongReadLen\n");
	    }
	if ((svp=hv_fetch((HV*)SvRV(attribs), "dbmaker_blob_size",15, 0)) != NULL)

dbdimp.c  view on Meta::CPAN

		        sv_setpvn(sv, p0, len);
			break;
			}
		    /* no ChopBlank */
		    if (fbh->ftype == SQL_C_FILE) /* #007 */
                sv_setpvn(sv, (char*)fbh->data, strlen(fbh->data));
            else
                sv_setpvn(sv, (char*)fbh->data, fbh->datalen);
		    break;
		}
	    }
	else 
	    {
	    SvOK_off(sv);
	    }
	}

#if DBMAKER_FILE_INOUT  
    /* 
     * #004 This can be done by SQLGetData, but use dbmaker's way seems easier.
     */
    if (imp_sth->fgBindColToFile)
       {
       int i;
       imp_fbh_t *fbh;
       for (fbh=imp_sth->fbh, i=0; i<imp_sth->n_result_cols; i++, fbh++)
           {
           if (fbh->ftype == SQL_C_FILE) 
              {
              char buf[MAX_FILE_NAME_LEN];
              struct stat  fbuf;
              do {
                fbh->file_idxno++;
                if (fbh->file_ext)
                   sprintf(fbh->data, "%s%d%s", fbh->file_prefix, fbh->file_idxno,fbh->file_ext);
                else
                   sprintf(fbh->data, "%s%d", fbh->file_prefix, fbh->file_idxno);
              } while(!fbh->fgOverwrite && !stat(fbh->data, &fbuf)); /* #008 */
              
              if (dbis->debug >= 2)
                  fprintf(DBILOGFP, 
		    "\tRebind/BindColToFile: col#%d to file:[%s]\n", i+1, fbh->data);
              }
           }
       }
#endif    	

    return av;
    }

int
dbd_st_finish(sth)
    SV *sth;
{
    D_imp_sth(sth);
    D_imp_dbh_from_sth;
    D_imp_drh_from_dbh;
    RETCODE rc;
    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);
	dbmaker_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))
	    {
    	    rc = SQLTransact(imp_drh->henv, 
		             imp_dbh->hdbc,
		             SQL_COMMIT);
	    }
#endif
	}
    DBIc_ACTIVE_off(imp_sth);

    return ret;
    }

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

    /* 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)
	{
	rc = SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
#if 0	
	if (rc != SQL_SUCCESS)
	    {
	    warn("warning: DBD::DBMaker SQLFreeStmt(SQL_DROP) returns %d\n", rc);
	    }
#endif	    
	}

    /* Free contents of imp_sth	*/

    Safefree(imp_sth->fbh);
    Safefree(imp_sth->ColNames);
    Safefree(imp_sth->RowBuffer);
    Safefree(imp_sth->statement);

    if (imp_sth->params_av)
	{
	av_undef(imp_sth->params_av);
	imp_sth->params_av = NULL;
	}

    if (imp_sth->params_hv)

dbdimp.c  view on Meta::CPAN

	    break;
	default:
	    if (vParam == pars->true)
		retsv = newSViv(1);
	    else
		retsv = newSViv(0);
	    break;
	} /* switch */
    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("dbm_type"),		/* 7 */
    s_A("dbm_length"),		/* 8 */
    s_A("CursorName"),		/* 9 */
    s_A("blob_size"),		/* 10 */
    s_A("__handled_by_dbi__"),	/* 11 */	/* ChopBlanks */
    s_A("dbmaker_blob_size"),	/* 12 */
    s_A("dbmaker_type"),		/* 13 */
    s_A("dbmaker_length"),	    /* 14 */
    s_A("LongReadLen"),		    /* 15 */
    s_A("dbmaker_file_input"),   /* 16 */       /* #004 */
    s_A(""),			/* END */
};

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

/*----------------------------------------
 * dummy routines st_XXXX
 *----------------------------------------
 */
SV *
dbd_st_FETCH(sth, keysv)
    SV *sth;
    SV *keysv;
{
    D_imp_sth(sth);
    STRLEN kl;
    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 'dbm_type'. "
		     "Please use 'dbmaker_type' instead.");
	    /* fall through */
	case 13:		/* dbmaker_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 'dbm_length'. "
		     "Please use 'dbmaker_length' instead.");
	    /* fall through */
	case 14:		/* dbmaker_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);
	    dbmaker_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 'dbmaker_blob_size' instead.");
	    /* fall through */
	case 12:		/* dbmaker_blob_size */
	case 15: 		/* LongReadLen */
	    retsv = newSViv(DBIc_LongReadLen(imp_sth));
	    break;
	    
	case 16:        /* dbmaker_file_input #004 */
	    retsv = newSViv(imp_sth->fgfileinput);
	    break;
	    
	default:
	    return Nullsv;
	}

    return sv_2mortal(retsv);
    }

int
dbd_st_STORE(sth, keysv, valuesv)
    SV *sth;
    SV *keysv;
    SV *valuesv;
{
    D_imp_sth(sth);
    D_imp_dbh_from_sth;
    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:/* dbmaker_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;
	    break;

dbdimp.c  view on Meta::CPAN


int
   build_results(sth)
   SV *	 sth;
{
    RETCODE rc;
    D_imp_sth(sth);

    if (DBIS->debug >= 2)
	fprintf(DBILOGFP, "    build_results 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->RowCount = -1;
    imp_sth->eod = -1;
#if DBMAKER_FILE_INOUT    /* #004 */  
    imp_sth->fgfileinput = 1;
    imp_sth->fgBindColToFile = 0;
#else
    imp_sth->fgfileinput = 0;
    imp_sth->fgBindColToFile = 0; 
#endif    

    if (!dbd_describe(sth, imp_sth)) {
	SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
	imp_sth->hstmt = SQL_NULL_HSTMT;
	return 0; /* dbd_describe already called ora_error()	*/
    }

    if (dbd_describe(sth, imp_sth) <= 0)
	return 0;

    DBIc_IMPSET_on(imp_sth);

    imp_sth->RowCount = -1;
    rc = SQLRowCount(imp_sth->hstmt, &imp_sth->RowCount);
    dbmaker_error(sth, rc, "dbd_st_tables/SQLRowCount");
    if (rc != SQL_SUCCESS) {
	return -1;
    }

    DBIc_ACTIVE_on(imp_sth); /* XXX should only set for select ?	*/
    imp_sth->eod = SQL_SUCCESS;
    return 1;
}

int
dbd_st_get_type_info(dbh, sth, ftype)
    SV *dbh;
    SV *sth;
    int ftype;
{
    dTHR;
    D_imp_dbh(dbh);
    D_imp_sth(sth);
    RETCODE rc;
    SV **svp;
    char cname[128];			/* cursorname */

    imp_sth->done_desc = 0;
    rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);
    if (rc != SQL_SUCCESS) {
	dbmaker_error(sth, rc, "dbmaker_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);

    dbmaker_error(sth, rc, "dbmaker_get_type_info/SQLGetTypeInfo");
    if (!SQL_ok(rc)) {
	SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
	imp_sth->hstmt = SQL_NULL_HSTMT;
	return 0;
    }

    return build_results(sth);
}

SV *
dbmaker_get_info(dbh, ftype)
    SV *dbh;
    int ftype;
{
    dTHR;
    D_imp_dbh(dbh);
    RETCODE rc;
    SV *retsv = NULL;
    int i;
    char rgbInfoValue[256];
    SWORD cbInfoValue = -2;

    /* See fancy logic below */
    for (i = 0; i < 6; i++)
	rgbInfoValue[i] = 0xFF;
    
    rc = SQLGetInfo(imp_dbh->hdbc, ftype,
	rgbInfoValue, sizeof(rgbInfoValue)-1, &cbInfoValue);
    if (!SQL_ok(rc)) {
	dbmaker_error(dbh, rc, "dbmaker_get_info/SQLGetInfo");
	return Nullsv;
    }

    /* Fancy logic here to determine if result is a string or int */
    if (cbInfoValue == -2)				/* is int */
	retsv = newSViv(*(int *)rgbInfoValue);	/* XXX cast */
    else if (cbInfoValue != 2 && cbInfoValue != 4)	/* must be string */
	retsv = newSVpv(rgbInfoValue, 0);
    else if (rgbInfoValue[cbInfoValue+1] == '\0')	/* must be string */
	retsv = newSVpv(rgbInfoValue, 0);
    else if (cbInfoValue == 2)			/* short */
	retsv = newSViv(*(short *)rgbInfoValue);	/* XXX cast */
    else if (cbInfoValue == 4)			/* int */
	retsv = newSViv(*(int *)rgbInfoValue);	/* XXX cast */



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