Esempio n. 1
0
BOOL CODBC::WriteScorcoData(char* SQL, BYTE* pData, int Length)
{
	SQLRETURN retcode;
	SQLINTEGER cbObjectParam;
	SQLPOINTER pToken;

	char* pSQL = new char[strlen(SQL)];
	sprintf(pSQL, SQL, "?");

	SQLFreeStmt(hstmt,SQL_CLOSE);
	retcode = SQLPrepare(hstmt, (unsigned char *)pSQL, SQL_NTS);
	if (MYSQLSUCCESS(rc))
	{
		SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 
			0, 0, (SQLPOINTER) 2, 0, &cbObjectParam);

		cbObjectParam = SQL_LEN_DATA_AT_EXEC(0);
		retcode = SQLExecute(hstmt);

		while (retcode == SQL_NEED_DATA)
		{
			retcode = SQLParamData(hstmt, &pToken);
			if (retcode == SQL_NEED_DATA)
				SQLPutData(hstmt, pData, Length);
		}
		return TRUE;
	}
	else
	{
		SaveSQLError();
		return FALSE;
	}
}
Esempio n. 2
0
static bool GetBufferInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
{
    info.ValueType = SQL_C_BINARY;

    const char* pb;
    Py_ssize_t  cb = PyBuffer_GetMemory(param, &pb);

    if (cb != -1 && cb <= cur->cnxn->binary_maxlength)
    {
        // There is one segment, so we can bind directly into the buffer object.

        info.ParameterType     = SQL_VARBINARY;
        info.ParameterValuePtr = (SQLPOINTER)pb;
        info.BufferLength      = cb;
        info.ColumnSize        = (SQLUINTEGER)max(cb, 1);
        info.StrLen_or_Ind     = cb;
    }
    else
    {
        // There are multiple segments, so we'll provide the data at execution time.  Pass the PyObject pointer as
        // the parameter value which will be pased back to us when the data is needed.  (If we release threads, we
        // need to up the refcount!)

        info.ParameterType     = SQL_LONGVARBINARY;
        info.ParameterValuePtr = param;
        info.ColumnSize        = (SQLUINTEGER)PyBuffer_Size(param);
        info.BufferLength      = sizeof(PyObject*); // How big is ParameterValuePtr; ODBC copies it and gives it back in SQLParamData
        info.StrLen_or_Ind     = cur->cnxn->need_long_data_len ? SQL_LEN_DATA_AT_EXEC((SQLLEN)PyBuffer_Size(param)) : SQL_DATA_AT_EXEC;
    }

    return true;
}
Esempio n. 3
0
void CQuery::WriteBlob(LPCTSTR szSQL, void *buf, int size)
{
	SQLINTEGER cbBlob;
	char tmp[BLOBBATCH],*p;
	SQLPOINTER pToken;
	int nPut;

	//LogAdd("%s", szSQL);

	cbBlob=SQL_LEN_DATA_AT_EXEC(size);
	SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_BINARY,SQL_LONGVARBINARY,
		size,0,(SQLPOINTER)1,0,&cbBlob);
	SQLExecDirect(hStmt,(SQLCHAR *)szSQL,SQL_NTS);
	ret=SQLParamData(hStmt, &pToken);
	while (ret==SQL_NEED_DATA) {
		if (ret==SQL_NEED_DATA) {
			if ((int)pToken==1) {
				for (p=(char *)buf;p<(char *)buf+size;p+=BLOBBATCH) {
					nPut=min(BLOBBATCH,(char *)buf+size-p);
					memcpy(tmp,p,nPut);
					SQLPutData(hStmt,(PTR)tmp,nPut);
				}
			}
		}
		ret=SQLParamData(hStmt, &pToken);
	}
	Clear();
}
Esempio n. 4
0
static bool GetBytesInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
{
    // In Python 2, a bytes object (ANSI string) is passed as varchar.  In Python 3, it is passed as binary.

    Py_ssize_t len = PyBytes_GET_SIZE(param);

#if PY_MAJOR_VERSION >= 3
    info.ValueType = SQL_C_BINARY;
    info.ColumnSize = (SQLUINTEGER)max(len, 1);

    if (len <= cur->cnxn->binary_maxlength)
    {
        info.ParameterType     = SQL_VARBINARY;
        info.StrLen_or_Ind     = len;
        info.ParameterValuePtr = PyBytes_AS_STRING(param);
    }
    else
    {
        // Too long to pass all at once, so we'll provide the data at execute.
        info.ParameterType     = SQL_LONGVARBINARY;
        info.StrLen_or_Ind     = cur->cnxn->need_long_data_len ? SQL_LEN_DATA_AT_EXEC((SQLLEN)len) : SQL_DATA_AT_EXEC;
        info.ParameterValuePtr = param;
    }

#else
    info.ValueType = SQL_C_CHAR;
    info.ColumnSize = (SQLUINTEGER)max(len, 1);

    if (len <= cur->cnxn->varchar_maxlength)
    {
        info.ParameterType     = SQL_VARCHAR;
        info.StrLen_or_Ind     = len;
        info.ParameterValuePtr = PyBytes_AS_STRING(param);
    }
    else
    {
        // Too long to pass all at once, so we'll provide the data at execute.
        info.ParameterType     = SQL_LONGVARCHAR;
        info.StrLen_or_Ind     = cur->cnxn->need_long_data_len ? SQL_LEN_DATA_AT_EXEC((SQLLEN)len) : SQL_DATA_AT_EXEC;
        info.ParameterValuePtr = param;
    }
#endif

    info.fnToPyObject = ToBytesInfo;

    return true;
}
Esempio n. 5
0
static bool GetUnicodeInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
{
    Py_UNICODE* pch = PyUnicode_AsUnicode(param);
    Py_ssize_t  len = PyUnicode_GET_SIZE(param);

    info.ValueType  = SQL_C_WCHAR;
    info.ColumnSize = (SQLUINTEGER)max(len, 1);

    if (len <= cur->cnxn->wvarchar_maxlength)
    {
        if (SQLWCHAR_SIZE == Py_UNICODE_SIZE)
        {
            info.ParameterValuePtr = pch;
        }
        else
        {
            // SQLWCHAR and Py_UNICODE are not the same size, so we need to allocate and copy a buffer.
            if (len > 0)
            {
                info.ParameterValuePtr = SQLWCHAR_FromUnicode(pch, len);
                if (info.ParameterValuePtr == 0)
                    return false;
                info.allocated = true;
            }
            else
            {
                info.ParameterValuePtr = pch;
            }
        }

        info.ParameterType = SQL_WVARCHAR;
        info.StrLen_or_Ind = (SQLINTEGER)(len * sizeof(SQLWCHAR));
    }
    else
    {
        // Too long to pass all at once, so we'll provide the data at execute.

        info.ParameterType     = SQL_WLONGVARCHAR;
        info.StrLen_or_Ind     = cur->cnxn->need_long_data_len ? SQL_LEN_DATA_AT_EXEC((SQLLEN)len * sizeof(SQLWCHAR)) : SQL_DATA_AT_EXEC;
        info.ParameterValuePtr = param;
    }

    return true;
}
Esempio n. 6
0
static void
add_test(SQLSMALLINT c_type, SQLSMALLINT sql_type, const char *db_type, unsigned gen1, unsigned gen2)
{
	test_info *t = NULL;
	size_t buf_len;

	if (num_tests >= MAX_TESTS) {
		fprintf(stderr, "too max tests\n");
		exit(1);
	}

	t = &test_infos[num_tests++];
	t->num = num_tests;
	t->c_type = c_type;
	t->sql_type = sql_type;
	t->db_type = db_type;
	t->gen1 = gen1;
	t->gen2 = gen2;
	t->vind = 0;
	switch (c_type) {
	case SQL_C_CHAR:
		buf_len =  NBYTES*2+1;
		break;
	case SQL_C_WCHAR:
		buf_len = (NBYTES*2+1) * sizeof(SQLWCHAR);
		break;
	default:
		buf_len = NBYTES;
	}
	t->buf = (char*) malloc(buf_len);
	if (!t->buf) {
		fprintf(stderr, "memory error\n");
		exit(1);
	}
	if (c_type != SQL_C_CHAR && c_type != SQL_C_WCHAR)
		fill_chars(t->buf, NBYTES, t->gen1, t->gen2);
	else
		memset(t->buf, 0, buf_len);
	t->vind = SQL_LEN_DATA_AT_EXEC(buf_len);
}
Esempio n. 7
0
static bool GetByteArrayInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
{
    info.ValueType = SQL_C_BINARY;

    Py_ssize_t cb = PyByteArray_Size(param);
    if (cb <= cur->cnxn->binary_maxlength)
    {
        info.ParameterType     = SQL_VARBINARY;
        info.ParameterValuePtr = (SQLPOINTER)PyByteArray_AsString(param);
        info.BufferLength      = cb;
        info.ColumnSize        = (SQLUINTEGER)max(cb, 1);
        info.StrLen_or_Ind     = cb;
    }
    else
    {
        info.ParameterType     = SQL_LONGVARBINARY;
        info.ParameterValuePtr = param;
        info.ColumnSize        = (SQLUINTEGER)cb;
        info.BufferLength      = sizeof(PyObject*); // How big is ParameterValuePtr; ODBC copies it and gives it back in SQLParamData
        info.StrLen_or_Ind     = cur->cnxn->need_long_data_len ? SQL_LEN_DATA_AT_EXEC((SQLLEN)cb) : SQL_DATA_AT_EXEC;
    }
    return true;
}
Esempio n. 8
0
int SSmain(int    argc, 
		SSchar* argv[])
{
	HDBC	hdbc;
	HENV	henv;
	HSTMT	hstmt;
	SQLRETURN  return_code;


	UTLDbUtlProgStart (argc, argv, SSText("log.txt"), DB_PD_DDL_EXPORT_PROCNAME);

	/*1. Connect to DB*/
	connectDB(&henv, &hdbc);

    /* HSTMT   hstmt_session;
    return_code = SQLAllocStmt ((SQLHDBC)hdbc, (SQLHSTMT *)&hstmt_session);
	if (return_code != SQL_SUCCESS)
	{
		printf("ERROR: The SQL statement did not execute successfully.\n");
		exit(1);
	}

   return_code = SQLExecDirect(hstmt_session, SSText("alter session set NLS_LANGUAGE='SIMPLIFIED CHINESE'"), -3);
   SQLFreeStmt(hstmt_session, SQL_DROP);*/

	/*3. Execute the SQL statement*/
	return_code = SQLAllocStmt ((SQLHDBC)hdbc, (SQLHSTMT *)&hstmt);
	if (return_code != SQL_SUCCESS)
	{  
		printf("ERROR: The SQL statement did not execute successfully.\n");
		exit(1);
	}
	
	SSchar*     pFilterStmt =  SSText("INSERT INTO TEST_CLOB_COL VALUES (?)");
	//SSchar*     pFilterStmt =  SSText("INSERT INTO test(LOG_DATA_1) VALUES (?)");
	return_code = SQLPrepare(hstmt, (SSuchar*)(pFilterStmt), SQL_NTS);   
	SSchar clobcol[] = {0x3042,0x3044,0x3046,0x3048,0x304A, 0x0000};
   /* test 1:
	LONG        cbRowId = 10;
	//return_code= SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_VARCHAR, 4000, 0, clobcol, sizeof(clobcol), &cbRowId); //This is ok!
	return_code= SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_LONGVARCHAR, 40, 0, clobcol, 10, &cbRowId);
    
	return_code = SQLExecute((SQLHSTMT)hstmt); 
   */

   /*test 2*/
   //test a: LONG cbRowId = SQL_DATA_AT_EXEC;
   LONG cbRowId = SQL_LEN_DATA_AT_EXEC(11);
   return_code= SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_LONGVARCHAR, 40, 0, clobcol, 10, &cbRowId);
   return_code = SQLExecute((SQLHSTMT)hstmt);
   SSchar *buf = clobcol;
   return_code = SQLParamData(hstmt, (SQLPOINTER *)&buf);
   return_code = SQLPutData(hstmt, buf, 10);
   return_code = SQLParamData(hstmt, (SQLPOINTER *)&buf);

	if (return_code == SQL_SUCCESS)
	{
		printf("The SQL statement executed successfully.\n");
	}
	else{
		printf("The SQL statement did not execute successfully.\n");
		ODBC_error ((HENV)henv, (HDBC)hdbc, (HSTMT)hstmt) ;
	}

   SSchar*     pSelectStmt =  SSText("select userenv('language') from dual");
	//SSchar*     pFilterStmt =  SSText("INSERT INTO test(LOG_DATA_1) VALUES (?)");
	return_code = SQLPrepare(hstmt, (SSuchar*)(pSelectStmt), SQL_NTS);

	return_code = SQLExecute((SQLHSTMT)hstmt); 
   

	SQLDisconnect ((SQLHDBC)hdbc);
	SQLFreeConnect ((SQLHDBC)hdbc);
	SQLFreeEnv ((SQLHENV)henv);

	return(return_code);
}
Esempio n. 9
0
int
main(int argc, char *argv[])
{
	SQLLEN ind;
	int len = strlen(test_text), n, i;
	const char *p;
	char *pp;
	SQLPOINTER ptr;
	unsigned char buf[256], *pb;
	SQLRETURN RetCode;
	int type, lc, sql_type;

	odbc_connect();

	/* create table to hold data */
	odbc_command("CREATE TABLE #putdata (c TEXT NULL, b IMAGE NULL)");

	sql_type = SQL_LONGVARCHAR;
	type = SQL_C_CHAR;
	lc = 1;
	for (;;) {
		CHKBindParameter(1, SQL_PARAM_INPUT, type, sql_type, 0, 0, (SQLPOINTER) 123, 0, &ind, "S");
		/* length required */
		ind = SQL_LEN_DATA_AT_EXEC(len * lc);

		/* 
		 * test for char 
		 */

		CHKPrepare(T("INSERT INTO #putdata(c) VALUES(?)"), SQL_NTS, "S");

		CHKExecute("Ne");

		p = test_text;
		n = 5;
		CHKParamData(&ptr, "Ne");
		if (ptr != (SQLPOINTER) 123)
			ODBC_REPORT_ERROR("Wrong pointer from SQLParamData");
		while (*p) {
			int l = strlen(p);

			if (l < n)
				n = l;
			if (type == SQL_C_CHAR) {
				CHKPutData((char *) p, n, "S");
			} else {
				SQLWCHAR buf[256];
				CHKPutData((char *) buf, to_sqlwchar(buf, p, n), "S");
			}
			p += n;
			n *= 2;
		}
		CHKParamData(&ptr, "S");

		CHKParamData(&ptr, "E");

		/* check state  and reset some possible buffers */
		odbc_command("DECLARE @i INT");

		/* use server ntext if available */
		if (sql_type == SQL_LONGVARCHAR && odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) {
			sql_type = SQL_WLONGVARCHAR;
			continue;
		}

		if (type != SQL_C_CHAR)
			break;
		sql_type = SQL_LONGVARCHAR;
		type = SQL_C_WCHAR;
		lc = sizeof(SQLWCHAR);
	}

	/* update row setting binary field */
	for (i = 0; i < 255; ++i)
		buf[i] = BYTE_AT(i);

	/* 
	 * test for binary 
	 */

	CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 0, 0, (SQLPOINTER) 4567, 0, &ind, "S");
	ind = SQL_LEN_DATA_AT_EXEC(254);

	CHKPrepare(T("UPDATE #putdata SET b = ?"), SQL_NTS, "S");

	CHKExecute("Ne");

	pb = buf;
	n = 7;
	CHKParamData(&ptr, "Ne");
	if (ptr != (SQLPOINTER) 4567)
		ODBC_REPORT_ERROR("Wrong pointer from SQLParamData");
	while (pb != (buf + 254)) {
		int l = buf + 254 - pb;

		if (l < n)
			n = l;
		CHKPutData((char *) pb, n, "S");
		pb += n;
		n *= 2;
	}
	CHKParamData(&ptr, "S");

	CHKParamData(&ptr, "E");

	/* check state  and reset some possible buffers */
	odbc_command("DECLARE @i2 INT");


	CHKFreeStmt(SQL_RESET_PARAMS, "S");

	/* check inserts ... there should be all equal rows */
	strcpy(sql, "IF EXISTS(SELECT * FROM #putdata WHERE CONVERT(VARBINARY(255),b) <> 0x");
	/* append binary */
	for (i = 0; i < 254; ++i)
		sprintf(strchr(sql, 0), "%02x", buf[i]);
	strcat(sql, " OR CONVERT(VARCHAR(255),c) <> '");
	/* append string */
	pp = strchr(sql, 0);
	p = test_text;
	do {
		*pp++ = *p;
		if (*p == '\'')
			*pp++ = *p;
	} while(*p++);
	strcat(sql, "') SELECT 1");
	odbc_check_no_row(sql);

	odbc_command("DELETE FROM #putdata");

	/* test len == 0 case from ML */
	type = SQL_C_CHAR;
	for (;;) {
		CHKPrepare(T("INSERT INTO #putdata(c) VALUES(?)"), SQL_NTS, "S");

		CHKBindParameter(1, SQL_PARAM_INPUT, type, SQL_LONGVARCHAR, 0, 0, (PTR) 2, 0, &ind, "S");

		ind = SQL_LEN_DATA_AT_EXEC(0);

		RetCode = CHKExecute("Ne");
		while (RetCode == SQL_NEED_DATA) {
			RetCode = SQLParamData(odbc_stmt, &ptr);
			if (RetCode == SQL_NEED_DATA) {
				if (type == SQL_C_CHAR) {
					CHKPutData("abc", 3, "S");
				} else {
					SQLWCHAR buf[10];
					CHKPutData(buf, to_sqlwchar(buf, "abc", 3), "S");
				}
			}
		}
		if (type != SQL_C_CHAR)
			break;
		type = SQL_C_WCHAR;
		odbc_reset_statement();
	}

	/* check inserts ... */
	odbc_check_no_row("IF EXISTS(SELECT * FROM #putdata WHERE c NOT LIKE 'abc') SELECT 1");

	odbc_command("DELETE FROM #putdata");

	/* test putting 0 bytes from Sebastien Flaesch */
	if (odbc_db_is_microsoft()) {
		type = SQL_C_CHAR;
		for (;;) {
			CHKPrepare(T("INSERT INTO #putdata(c) VALUES(?)"), SQL_NTS, "S");

			CHKBindParameter(1, SQL_PARAM_INPUT, type, SQL_LONGVARCHAR, 10, 0, (PTR) 2, 10, &ind, "S");

			ind = SQL_DATA_AT_EXEC;

			RetCode = CHKExecute("Ne");
			while (RetCode == SQL_NEED_DATA) {
				RetCode = SQLParamData(odbc_stmt, &ptr);
				if (RetCode == SQL_NEED_DATA)
					CHKPutData("", 0, "S");
			}
			if (type != SQL_C_CHAR)
				break;
			type = SQL_C_WCHAR;
			odbc_reset_statement();
		}

		/* check inserts ... */
		odbc_check_no_row("IF EXISTS(SELECT * FROM #putdata WHERE c NOT LIKE '') SELECT 1");
	}

	/* TODO test cancel inside SQLExecute */

	odbc_disconnect();

	printf("Done.\n");
	return 0;
}
Esempio n. 10
0
CSqlRecordsetPtr CMssqlConnection::_Execute(const char *string)
{
	cvs::string str = string;
	SQLRETURN ret;

	CMssqlRecordset *rs = new CMssqlRecordset();

	CServerIo::trace(3,"%s",str.c_str());

	bool inquote = false;
	for(size_t n=0; n<str.size(); n++)
	{
		if(str[n]=='\'')
		{
			inquote = !inquote;
			if(inquote)
				str.insert(n++,1,'N');
		}
	}

	HSTMT hStmt;

	if(!SQL_SUCCEEDED(m_lasterror=SQLAllocHandle(SQL_HANDLE_STMT,m_hDbc,&hStmt)))
	{
		SQLFreeStmt(hStmt,SQL_DROP);
		return rs;
	}

	for(std::map<int,CSqlVariant>::iterator i = m_bindVars.begin(); i!=m_bindVars.end(); ++i)
	{
		switch(i->second.type())
		{
		case CSqlVariant::vtNull:
			m_sqli[i->first]=SQL_NULL_DATA;
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,0,0,NULL,0,&m_sqli[i->first]);
			break;
		case CSqlVariant::vtChar:
			CServerIo::trace(3,"Bind vtChar (SQL Server) = \"%c\"",m_sqlv[i->first].c);
			m_sqli[i->first]=0;
			m_sqlv[i->first].c=i->second;
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,1,0,&m_sqlv[i->first].c,1,&m_sqli[i->first]);
			break;
		case CSqlVariant::vtUChar:
			m_sqli[i->first]=0;
			m_sqlv[i->first].c=i->second;
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,1,0,&m_sqlv[i->first].c,1,&m_sqli[i->first]);
			break;
		case CSqlVariant::vtShort:
			m_sqli[i->first]=0;
			m_sqlv[i->first].s=i->second;
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_SSHORT,SQL_INTEGER,0,0,&m_sqlv[i->first].s,0,&m_sqli[i->first]);
			break;
		case CSqlVariant::vtUShort:
			m_sqli[i->first]=0;
			m_sqlv[i->first].s=i->second;
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_USHORT,SQL_INTEGER,0,0,&m_sqlv[i->first].s,0,&m_sqli[i->first]);
			break;
		case CSqlVariant::vtInt:
		case CSqlVariant::vtLong:
			m_sqli[i->first]=0;
			m_sqlv[i->first].l=i->second;
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_SLONG,SQL_INTEGER,0,0,&m_sqlv[i->first].l,0,&m_sqli[i->first]);
			break;
		case CSqlVariant::vtUInt:
		case CSqlVariant::vtULong:
			m_sqli[i->first]=0;
			m_sqlv[i->first].l=i->second;
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&m_sqlv[i->first].l,0,&m_sqli[i->first]);
			break;
		case CSqlVariant::vtLongLong:
			m_sqli[i->first]=0;
			m_sqlv[i->first].ll=i->second;
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_SBIGINT,SQL_BIGINT,0,0,&m_sqlv[i->first].ll,0,&m_sqli[i->first]);
			break;
		case CSqlVariant::vtULongLong:
			m_sqli[i->first]=0;
			m_sqlv[i->first].ll=i->second;
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_UBIGINT,SQL_BIGINT,0,0,&m_sqlv[i->first].ll,0,&m_sqli[i->first]);
			break;
		case CSqlVariant::vtString:
			CServerIo::trace(3,"Bind vtString (SQL Server)"); 

			if (m_sqlv[i->first].ws.length()+1<256)
			{
				CServerIo::trace(3,"Bind vtString as type SQL_NTS (Null Terminated String)");
			m_sqli[i->first]=SQL_NTS;
			m_sqlv[i->first].ws=cvs::wide(i->second);
				CServerIo::trace(3,"Bind vtString as SQL_VARCHAR/text C_WCHAR");
				ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_WCHAR,SQL_VARCHAR,(SQLINTEGER)m_sqlv[i->first].ws.size()+1,0,(SQLPOINTER)m_sqlv[i->first].ws.c_str(),(SQLINTEGER)m_sqlv[i->first].ws.size(),&m_sqli[i->first]);
			}
			else
			{
				CServerIo::trace(3,"Bind vtString as type LEN_DATA_AT_EXEC");
				m_sqli[i->first]=SQL_LEN_DATA_AT_EXEC((SQLINTEGER)((m_sqlv[i->first].ws.size()+1)*sizeof(wchar_t)));
				m_sqlv[i->first].ws=cvs::wide(i->second);
				CServerIo::trace(3,"Bind vtString as SQL_WLONGVARCHAR/text BLOB");
				ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_WCHAR,SQL_WLONGVARCHAR,(SQLINTEGER)((m_sqlv[i->first].ws.size()+1)*sizeof(wchar_t)),0,(VOID *)NULL,0,&m_sqli[i->first]);
			}
			break;
		case CSqlVariant::vtWString:
			CServerIo::trace(3,"Bind vtWString (SQL Server)"); 
			m_sqli[i->first]=SQL_NTS;
			m_sqlv[i->first].ws=i->second;
			CServerIo::trace(3,"Bind vtWString (SQL Server)");
			ret = SQLBindParameter(hStmt,i->first+1,SQL_PARAM_INPUT,SQL_C_WCHAR,SQL_WVARCHAR,(SQLINTEGER)m_sqlv[i->first].ws.size()+1,0,(SQLPOINTER)m_sqlv[i->first].ws.c_str(),(SQLINTEGER)m_sqlv[i->first].ws.size()+1,&m_sqli[i->first]);
			break;
		}
	}

	CServerIo::trace(3,"%s",str.c_str());

	rs->Init(this,hStmt,str.c_str()); // Ignore return... it's handled by the error routines

	m_bindVars.clear();

	return rs;
}
Esempio n. 11
0
static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
		enum pdo_param_event event_type)
{
	pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
	RETCODE rc;
	SWORD sqltype = 0, ctype = 0, scale = 0, nullable = 0;
	SQLULEN precision = 0;
	pdo_odbc_param *P;
	zval *parameter;
	
	/* we're only interested in parameters for prepared SQL right now */
	if (param->is_param) {

		switch (event_type) {
			case PDO_PARAM_EVT_FETCH_PRE:
			case PDO_PARAM_EVT_FETCH_POST:
			case PDO_PARAM_EVT_NORMALIZE:
				/* Do nothing */
				break;

			case PDO_PARAM_EVT_FREE:
				P = param->driver_data;
				if (P) {
					efree(P);
				}
				break;

			case PDO_PARAM_EVT_ALLOC:
			{
				/* figure out what we're doing */
				switch (PDO_PARAM_TYPE(param->param_type)) {
					case PDO_PARAM_LOB:
						break;

					case PDO_PARAM_STMT:
						return 0;
					
					default:
						break;
				}

				rc = SQLDescribeParam(S->stmt, (SQLUSMALLINT) param->paramno+1, &sqltype, &precision, &scale, &nullable);
				if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
					/* MS Access, for instance, doesn't support SQLDescribeParam,
					 * so we need to guess */
					sqltype = PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB ?
									SQL_LONGVARBINARY :
									SQL_LONGVARCHAR;
					precision = 4000;
					scale = 5;
					nullable = 1;

					if (param->max_value_len > 0) {
						precision = param->max_value_len;
					}
				}
				if (sqltype == SQL_BINARY || sqltype == SQL_VARBINARY || sqltype == SQL_LONGVARBINARY) {
					ctype = SQL_C_BINARY;
				} else {
					ctype = SQL_C_CHAR;
				}

				P = emalloc(sizeof(*P));
				param->driver_data = P;

				P->len = 0; /* is re-populated each EXEC_PRE */
				P->outbuf = NULL;

				P->is_unicode = pdo_odbc_sqltype_is_unicode(S, sqltype);
				if (P->is_unicode) {
					/* avoid driver auto-translation: we'll do it ourselves */
					ctype = SQL_C_BINARY;
				}

				if ((param->param_type & PDO_PARAM_INPUT_OUTPUT) == PDO_PARAM_INPUT_OUTPUT) {
					P->paramtype = SQL_PARAM_INPUT_OUTPUT;
				} else if (param->max_value_len <= 0) {
					P->paramtype = SQL_PARAM_INPUT;
				} else {
					P->paramtype = SQL_PARAM_OUTPUT;
				}
				
				if (P->paramtype != SQL_PARAM_INPUT) {
					if (PDO_PARAM_TYPE(param->param_type) != PDO_PARAM_NULL) {
						/* need an explicit buffer to hold result */
						P->len = param->max_value_len > 0 ? param->max_value_len : precision;
						if (P->is_unicode) {
							P->len *= 2;
						}
						P->outbuf = emalloc(P->len + (P->is_unicode ? 2:1));
					}
				}
				
				if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB && P->paramtype != SQL_PARAM_INPUT) {
					pdo_odbc_stmt_error("Can't bind a lob for output");
					return 0;
				}

				rc = SQLBindParameter(S->stmt, (SQLUSMALLINT) param->paramno+1,
						P->paramtype, ctype, sqltype, precision, scale,
						P->paramtype == SQL_PARAM_INPUT ? 
							(SQLPOINTER)param :
							P->outbuf,
						P->len,
						&P->len
						);
	
				if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
					return 1;
				}
				pdo_odbc_stmt_error("SQLBindParameter");
				return 0;
			}

			case PDO_PARAM_EVT_EXEC_PRE:
				P = param->driver_data;
				if (!Z_ISREF(param->parameter)) {
					parameter = &param->parameter;
				} else {
					parameter = Z_REFVAL(param->parameter);
				}

				if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
					if (Z_TYPE_P(parameter) == IS_RESOURCE) {
						php_stream *stm;
						php_stream_statbuf sb;

						php_stream_from_zval_no_verify(stm, parameter);

						if (!stm) {
							return 0;
						}

						if (0 == php_stream_stat(stm, &sb)) {
							if (P->outbuf) {
								int len, amount;
								char *ptr = P->outbuf;
								char *end = P->outbuf + P->len;

								P->len = 0;
								do {
									amount = end - ptr;
									if (amount == 0) {
										break;
									}
									if (amount > 8192)
										amount = 8192;
									len = php_stream_read(stm, ptr, amount);
									if (len == 0) {
										break;
									}
									ptr += len;
									P->len += len;
								} while (1);

							} else {
								P->len = SQL_LEN_DATA_AT_EXEC(sb.sb.st_size);
							}
						} else {
							if (P->outbuf) {
								P->len = 0;
							} else {
								P->len = SQL_LEN_DATA_AT_EXEC(0);
							}
						}
					} else {
						convert_to_string(parameter);
						if (P->outbuf) {
							P->len = Z_STRLEN_P(parameter);
							memcpy(P->outbuf, Z_STRVAL_P(parameter), P->len);
						} else {
							P->len = SQL_LEN_DATA_AT_EXEC(Z_STRLEN_P(parameter));
						}
					}
				} else if (Z_TYPE_P(parameter) == IS_NULL || PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_NULL) {
					P->len = SQL_NULL_DATA;
				} else {
					convert_to_string(parameter);
					if (P->outbuf) {
						zend_ulong ulen;
						switch (pdo_odbc_utf82ucs2(stmt, P->is_unicode,
								Z_STRVAL_P(parameter),
								Z_STRLEN_P(parameter),
								&ulen)) {
							case PDO_ODBC_CONV_FAIL:
							case PDO_ODBC_CONV_NOT_REQUIRED:
								P->len = Z_STRLEN_P(parameter);
								memcpy(P->outbuf, Z_STRVAL_P(parameter), P->len);
								break;
							case PDO_ODBC_CONV_OK:
								P->len = ulen;
								memcpy(P->outbuf, S->convbuf, P->len);
								break;
						}
					} else {
						P->len = SQL_LEN_DATA_AT_EXEC(Z_STRLEN_P(parameter));
					}
				}
				return 1;
			
			case PDO_PARAM_EVT_EXEC_POST:
				P = param->driver_data;

				if (P->outbuf) {
					zend_ulong ulen;
					char *srcbuf;
					zend_ulong srclen = 0;

					if (Z_ISREF(param->parameter)) {
						parameter = Z_REFVAL(param->parameter);
					} else {
						parameter = &param->parameter;
					}
					zval_ptr_dtor(parameter);
					ZVAL_NULL(parameter);

					switch (P->len) {
						case SQL_NULL_DATA:
							break;
						default:
							switch (pdo_odbc_ucs22utf8(stmt, P->is_unicode, P->outbuf, P->len, &ulen)) {
								case PDO_ODBC_CONV_FAIL:
									/* something fishy, but allow it to come back as binary */
								case PDO_ODBC_CONV_NOT_REQUIRED:
									srcbuf = P->outbuf;
									srclen = P->len;
									break;
								case PDO_ODBC_CONV_OK:
									srcbuf = S->convbuf;
									srclen = ulen;
									break;
							}
										
							ZVAL_NEW_STR(parameter, zend_string_alloc(srclen, 0));
							memcpy(Z_STRVAL_P(parameter), srcbuf, srclen);
							Z_STRVAL_P(parameter)[Z_STRLEN_P(parameter)] = '\0';
					}
				}
				return 1;
		}
	}
	return 1;
}
Esempio n. 12
0
static BOOL kpc_bindparameter(ATOMID idfName, WORD h, LPFETCH lpFetch,
                              int nParam, ATOMID idMode, 
                              WORD wType, OBJECTID idObj, ATOMID idSlot,
                              BOOL bLive)
{
    WORD wMode;
    WORD sqlType = SQL_LONGVARCHAR, scale = 0, nullable = SQL_NO_NULLS;
    DWORD colDef = RET_BUFFER_LEN - 1;
    LPPARAM lpParams, lpParam;
    LPDESC lpDesc;
    WORD wNumParams = 0;
    DWORD dwLen;
    RETCODE code;
    
    if (idMode == Symbol(INPUT))
        wMode = SQL_PARAM_INPUT;
    else if (idMode == Symbol(OUTPUT))
        wMode = SQL_PARAM_OUTPUT;
    else if (idMode == Symbol(INPUT_OUTPUT))
        wMode = SQL_PARAM_INPUT_OUTPUT;
    
    code = SQLDescribeParam(lpFetch->hstmt, nParam,
                            &sqlType, &colDef, &scale, &nullable);
    
    switch (code) {
      case SQL_SUCCESS:
      case SQL_SUCCESS_WITH_INFO:
          break;
      case SQL_INVALID_HANDLE:
          return KPC_HANDLE_ERROR(IDE_INVALID_HANDLE, h);
      default:
          sql_error(idfName, SQL_NULL_HDBC, lpFetch->hstmt);
          if (!stricmp(sqlstate, "IM001"))
          {
              if (nParam < 1)
                  return KPC_ERROR(IDE_OUTOF_RANGE, KppAddAtomInt(nParam));
              if (!num_params(idfName, h, lpFetch->hstmt, &wNumParams))
                  return ERROR;
              if (nParam > wNumParams)
                  return KPC_ERROR(IDE_OUTOF_RANGE, KppAddAtomInt(nParam));
              
              sqlType = SQL_LONGVARCHAR;
              colDef = RET_BUFFER_LEN - 1;
              nullable = SQL_NO_NULLS;
          }
          else
              return ERROR;
    }

    if (!lpFetch->params)
    {
        if (!wNumParams && 
            !num_params(idfName, h, lpFetch->hstmt, &wNumParams))
            return ERROR;

        lpParams = calloc(sizeof(PARAM), wNumParams);
        if (!lpParams)
            return KPC_ERROR(IDE_OUTOF_MEMORY, NULLID);
    }
    else
        lpParams = lpFetch->params;
    
    lpParam = lpParams + nParam - 1;
    lpDesc = &lpParam->desc;
    lpDesc->sqlType = sqlType;
    lpDesc->colDef = colDef;
    lpDesc->scale = scale;
    lpDesc->nullable = nullable;

    if (lpFetch->wXParamRows)
    {
        lpDesc->pdwLen = calloc(sizeof(DWORD), lpFetch->wXParamRows + 1);
        if (!lpDesc->pdwLen)
            return KPC_ERROR(IDE_OUTOF_MEMORY, NULLID);
    }
    else
        lpDesc->pdwLen = &lpDesc->dwLen;
                  
    if (!fill_bind(idfName, lpDesc, &lpParam->data, 
                   lpFetch->wXParamRows, &dwLen))
    {
        free_params(lpParams, lpFetch->wNumParams);
        return ERROR;
    }
    else
    {
        lpParam->wMode = wMode;
        lpParam->wType = wType;
        lpParam->idObj = idObj;
        lpParam->idSlot = idSlot;
        lpDesc->colDef = dwLen;
        lpFetch->wNumParams = wNumParams;
        lpFetch->params = lpParams;
        
        if (bLive)
        {
            int i = -1;
            
            while (++i <= lpFetch->wXParamRows)
                lpDesc->pdwLen[i] = SQL_LEN_DATA_AT_EXEC(0);
        }
        else if (!set_parameter_value(idfName, lpParam, lpFetch->wXParamRows))
            return ERROR;
    }
    
    code = SQLBindParameter(lpFetch->hstmt, nParam, wMode, 
                            lpDesc->cType, lpDesc->sqlType,
                            lpDesc->colDef, lpDesc->scale,
                            lpDesc->address, dwLen, lpDesc->pdwLen);
    
    switch (code) {
      case SQL_SUCCESS:
      case SQL_SUCCESS_WITH_INFO:
          lpParam->bound = TRUE;
          return TRUE;
      case SQL_INVALID_HANDLE:
          return KPC_HANDLE_ERROR(IDE_INVALID_HANDLE, h);
      default:
          return sql_error(idfName, SQL_NULL_HDBC, lpFetch->hstmt);
    }          
}
Esempio n. 13
0
/**
 * Convert parameters to libtds format
 * @return SQL_SUCCESS, SQL_ERROR or SQL_NEED_DATA
 */
SQLRETURN
sql2tds(TDS_DBC * dbc, struct _drecord *drec_ipd, struct _drecord *drec_apd, TDSPARAMINFO * info, int nparam)
{
	int dest_type, src_type, res;
	CONV_RESULT ores;
	TDSBLOBINFO *blob_info;
	char *src;
	unsigned char *dest;
	TDSCOLINFO *curcol = info->columns[nparam];
	int len;
	TDS_DATETIME dt;
	TDS_NUMERIC num;
	SQL_NUMERIC_STRUCT *sql_num;
	SQLINTEGER sql_len;
	int need_data = 0, i;

	/* TODO handle bindings of char like "{d '2002-11-12'}" */
	tdsdump_log(TDS_DBG_INFO2, "%s:%d type=%d\n", __FILE__, __LINE__, drec_ipd->sql_desc_concise_type);

	/* what type to convert ? */
	dest_type = odbc_sql_to_server_type(dbc->tds_socket, drec_ipd->sql_desc_concise_type);
	if (dest_type == TDS_FAIL)
		return SQL_ERROR;
	tdsdump_log(TDS_DBG_INFO2, "%s:%d\n", __FILE__, __LINE__);

	/* TODO what happen for unicode types ?? */
	tds_set_param_type(dbc->tds_socket, curcol, dest_type);
	if (is_numeric_type(curcol->column_type)) {
		curcol->column_prec = drec_ipd->sql_desc_precision;
		curcol->column_scale = drec_ipd->sql_desc_scale;
	}

	if (drec_ipd->sql_desc_parameter_type != SQL_PARAM_INPUT)
		curcol->column_output = 1;

	/* compute destination length */
	if (curcol->column_varint_size != 0) {
		/* curcol->column_size = drec_apd->sql_desc_octet_length; */
		/*
		 * TODO destination length should come from sql_desc_length, 
		 * however there is the encoding problem to take into account
		 * we should fill destination length after conversion keeping 
		 * attention to fill correctly blob/fixed type/variable type
		 */
		curcol->column_cur_size = 0;
		curcol->column_size = drec_ipd->sql_desc_length;
		if (curcol->column_size < 0)
			curcol->column_size = 0x7FFFFFFFl;
	} else {
		/* TODO only a trick... */
		if (curcol->column_varint_size == 0)
			tds_set_param_type(dbc->tds_socket, curcol, tds_get_null_type(dest_type));
	}

	/* get C type */
	src_type = drec_apd->sql_desc_concise_type;
	if (src_type == SQL_C_DEFAULT)
		src_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);

	/* if only output assume input is NULL */
	if (drec_ipd->sql_desc_parameter_type == SQL_PARAM_OUTPUT)
		sql_len = SQL_NULL_DATA;
	else
		sql_len = odbc_get_param_len(dbc->tds_socket, drec_apd, drec_ipd);

	/* compute source length */
	switch (sql_len) {
	case SQL_NULL_DATA:
		len = 0;
		break;
	case SQL_NTS:
		len = strlen(drec_apd->sql_desc_data_ptr);
		break;
	case SQL_DEFAULT_PARAM:
	case SQL_DATA_AT_EXEC:
		/* TODO */
		return SQL_ERROR;
		break;
	default:
		len = sql_len;
		if (sql_len < 0) {
			/* test for SQL_C_CHAR/SQL_C_BINARY */
			switch (src_type) {
			case SQL_C_CHAR:
			case SQL_C_BINARY:
				break;
			default:
				return SQL_ERROR;
			}
			len = SQL_LEN_DATA_AT_EXEC(sql_len);
			need_data = 1;

			/* other trick, set length of destination */
			switch (odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type)) {
			case SQL_C_CHAR:
			case SQL_C_BINARY:
				curcol->column_size = len;
				break;
			}
		}
	}

	/* allocate given space */
	if (!tds_alloc_param_row(info, curcol))
		return SQL_ERROR;

	/* test source type */
	/* TODO test intervals */
	src_type = odbc_c_to_server_type(src_type);
	if (src_type == TDS_FAIL)
		return SQL_ERROR;

	if (need_data) {
		curcol->column_cur_size = 0;
		return SQL_NEED_DATA;
	}

	/* set null */
	assert(drec_ipd->sql_desc_parameter_type != SQL_PARAM_OUTPUT || sql_len == SQL_NULL_DATA);
	if (sql_len == SQL_NULL_DATA) {
		curcol->column_cur_size = 0;
		tds_set_null(info->current_row, nparam);
		return TDS_SUCCEED;
	}

	/* convert special parameters (not libTDS compatible) */
	src = drec_apd->sql_desc_data_ptr;
	switch (src_type) {
	case SYBDATETIME:
		convert_datetime2server(drec_apd->sql_desc_concise_type, src, &dt);
		src = (char *) &dt;
		break;
	case SYBDECIMAL:
	case SYBNUMERIC:
		sql_num = (SQL_NUMERIC_STRUCT *) src;
		num.precision = sql_num->precision;
		num.scale = sql_num->scale;
		num.array[0] = sql_num->sign ^ 1;
		/* TODO test precision so client do not crash our library ?? */
		i = tds_numeric_bytes_per_prec[num.precision];
		memcpy(num.array + 1, sql_num->val, i);
		tds_swap_bytes(num.array + 1, i);
		++i;
		if (i < sizeof(num.array))
			memset(num.array + i, 0, sizeof(num.array) - i);
		src = (char *) &num;

		/* set output */
		/* TODO use descriptors informations ?? */
		ores.n.precision = 18;
		ores.n.scale = 2;
		break;
		/* TODO intervals */
	}

	res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, &ores);
	if (res < 0)
		return SQL_ERROR;
	tdsdump_log(TDS_DBG_INFO2, "%s:%d\n", __FILE__, __LINE__);

	/* truncate ?? */
	/* TODO what happen for blobs ?? */
	if (res > curcol->column_size)
		res = curcol->column_size;
	curcol->column_cur_size = res;

	/* free allocated memory */
	dest = &info->current_row[curcol->column_offset];
	switch ((TDS_SERVER_TYPE) dest_type) {
	case SYBCHAR:
	case SYBVARCHAR:
	case XSYBCHAR:
	case XSYBVARCHAR:
		memcpy(&info->current_row[curcol->column_offset], ores.c, res);
		free(ores.c);
		break;
	case SYBTEXT:
		blob_info = (TDSBLOBINFO *) dest;
		if (blob_info->textvalue)
			free(blob_info->textvalue);
		blob_info->textvalue = ores.c;
		break;
	case SYBBINARY:
	case SYBVARBINARY:
	case XSYBBINARY:
	case XSYBVARBINARY:
		memcpy(&info->current_row[curcol->column_offset], ores.ib, res);
		free(ores.ib);
		break;
	case SYBLONGBINARY:
	case SYBIMAGE:
		blob_info = (TDSBLOBINFO *) dest;
		if (blob_info->textvalue)
			free(blob_info->textvalue);
		blob_info->textvalue = ores.ib;
		break;
	case SYBINTN:
	case SYBINT1:
	case SYBINT2:
	case SYBINT4:
	case SYBINT8:
	case SYBFLT8:
	case SYBDATETIME:
	case SYBBIT:
	case SYBMONEY4:
	case SYBMONEY:
	case SYBDATETIME4:
	case SYBREAL:
	case SYBBITN:
	case SYBNUMERIC:
	case SYBDECIMAL:
	case SYBFLTN:
	case SYBMONEYN:
	case SYBDATETIMN:
	case SYBSINT1:
	case SYBUINT2:
	case SYBUINT4:
	case SYBUINT8:
	case SYBUNIQUE:
		memcpy(&info->current_row[curcol->column_offset], &ores, res);
		break;
	case XSYBNVARCHAR:
	case XSYBNCHAR:
	case SYBNVARCHAR:
	case SYBNTEXT:
	case SYBVOID:
	case SYBVARIANT:
		/* TODO ODBC 3.5 */
		assert(0);
		break;
	}

	return SQL_SUCCESS;
}
Esempio n. 14
0
/**
 * Convert parameters to libtds format
 * @return SQL_SUCCESS, SQL_ERROR or SQL_NEED_DATA
 */
SQLRETURN
sql2tds(TDS_STMT * stmt, const struct _drecord *drec_ipd, const struct _drecord *drec_apd, TDSCOLUMN *curcol,
	int compute_row, const TDS_DESC* axd, unsigned int n_row)
{
	TDS_DBC * dbc = stmt->dbc;
	int dest_type, src_type, sql_src_type, res;
	CONV_RESULT ores;
	TDSBLOB *blob;
	char *src;
	unsigned char *dest;
	int len;
	TDS_DATETIME dt;
	TDS_NUMERIC num;
	SQL_NUMERIC_STRUCT *sql_num;
	SQLINTEGER sql_len;
	int need_data = 0, i;

	/* TODO handle bindings of char like "{d '2002-11-12'}" */
	tdsdump_log(TDS_DBG_INFO2, "type=%d\n", drec_ipd->sql_desc_concise_type);

	/* what type to convert ? */
	dest_type = odbc_sql_to_server_type(dbc->tds_socket, drec_ipd->sql_desc_concise_type);
	if (dest_type == TDS_FAIL)
		return SQL_ERROR;
	tdsdump_log(TDS_DBG_INFO2, "trace\n");

	/* TODO what happen for unicode types ?? */
	tds_set_param_type(dbc->tds_socket, curcol, dest_type);
	if (is_numeric_type(curcol->column_type)) {
		curcol->column_prec = drec_ipd->sql_desc_precision;
		curcol->column_scale = drec_ipd->sql_desc_scale;
	}

	if (drec_ipd->sql_desc_parameter_type != SQL_PARAM_INPUT)
		curcol->column_output = 1;

	/* compute destination length */
	if (curcol->column_varint_size != 0) {
		/* curcol->column_size = drec_apd->sql_desc_octet_length; */
		/*
		 * TODO destination length should come from sql_desc_length, 
		 * however there is the encoding problem to take into account
		 * we should fill destination length after conversion keeping 
		 * attention to fill correctly blob/fixed type/variable type
		 */
		/* TODO location of this test is correct here ?? */
		if (dest_type != SYBUNIQUE && dest_type != SYBBITN && !is_fixed_type(dest_type)) {
			curcol->column_cur_size = 0;
			curcol->column_size = drec_ipd->sql_desc_length;
			if (curcol->column_size < 0)
				curcol->column_size = 0x7FFFFFFFl;
		}
	} else if (dest_type != SYBBIT) {
		/* TODO only a trick... */
		tds_set_param_type(dbc->tds_socket, curcol, tds_get_null_type(dest_type));
	}

	/* get C type */
	sql_src_type = drec_apd->sql_desc_concise_type;
	if (sql_src_type == SQL_C_DEFAULT)
		sql_src_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);

	/* test source type */
	/* TODO test intervals */
	src_type = odbc_c_to_server_type(sql_src_type);
	if (src_type == TDS_FAIL)
		return SQL_ERROR;

	/* we have no data to convert, just return */
	if (!compute_row)
		return TDS_SUCCEED;

	src = drec_apd->sql_desc_data_ptr;
	if (src && n_row) {
		SQLLEN len;
		if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
			len = axd->header.sql_desc_bind_type;
			if (axd->header.sql_desc_bind_offset_ptr)
				src += *axd->header.sql_desc_bind_offset_ptr;
		} else {
			len = odbc_get_octet_len(sql_src_type, drec_apd);
			if (len < 0)
				/* TODO sure ? what happen to upper layer ?? */
				return SQL_ERROR;
		}
		src += len * n_row;
	}

	/* if only output assume input is NULL */
	if (drec_ipd->sql_desc_parameter_type == SQL_PARAM_OUTPUT) {
		sql_len = SQL_NULL_DATA;
	} else {
		sql_len = odbc_get_param_len(drec_apd, drec_ipd, axd, n_row);

		/* special case, MS ODBC handle conversion from "\0" to any to NULL, DBD::ODBC require it */
		if (src_type == SYBVARCHAR && sql_len == 1 && drec_ipd->sql_desc_parameter_type == SQL_PARAM_INPUT_OUTPUT
		    && src && *src == 0) {
			sql_len = SQL_NULL_DATA;
		}
	}

	/* compute source length */
	switch (sql_len) {
	case SQL_NULL_DATA:
		len = 0;
		break;
	case SQL_NTS:
		/* check that SQLBindParameter::ParameterValuePtr is not zero for input parameters */
		if (!src) {
			odbc_errs_add(&stmt->errs, "HY090", NULL);
			return SQL_ERROR;
		}
		len = strlen(src);
		break;
	case SQL_DEFAULT_PARAM:
	case SQL_DATA_AT_EXEC:
		/* TODO */
		return SQL_ERROR;
		break;
	default:
		len = sql_len;
		if (sql_len < 0) {
			/* test for SQL_C_CHAR/SQL_C_BINARY */
			switch (sql_src_type) {
			case SQL_C_CHAR:
			case SQL_C_BINARY:
				break;
			default:
				return SQL_ERROR;
			}
			len = SQL_LEN_DATA_AT_EXEC(sql_len);
			need_data = 1;

			/* dynamic length allowed only for BLOB fields */
			switch (drec_ipd->sql_desc_concise_type) {
			case SQL_LONGVARCHAR:
			case SQL_LONGVARBINARY:
				break;
			default:
				return SQL_ERROR;
			}
		}
	}

	/* allocate given space */
	if (!tds_alloc_param_data(curcol))
		return SQL_ERROR;

	if (need_data) {
		curcol->column_cur_size = 0;
		return SQL_NEED_DATA;
	}

	/* set null */
	assert(drec_ipd->sql_desc_parameter_type != SQL_PARAM_OUTPUT || sql_len == SQL_NULL_DATA);
	if (sql_len == SQL_NULL_DATA) {
		curcol->column_cur_size = -1;
		return TDS_SUCCEED;
	}

	if (!src) {
		odbc_errs_add(&stmt->errs, "HY090", NULL);
		return SQL_ERROR;
	}

	/* convert special parameters (not libTDS compatible) */
	switch (src_type) {
	case SYBDATETIME:
		convert_datetime2server(drec_apd->sql_desc_concise_type, src, &dt);
		src = (char *) &dt;
		break;
	case SYBDECIMAL:
	case SYBNUMERIC:
		sql_num = (SQL_NUMERIC_STRUCT *) src;
		num.precision = sql_num->precision;
		num.scale = sql_num->scale;
		num.array[0] = sql_num->sign ^ 1;
		/* test precision so client do not crash our library */
		if (num.precision <= 0 || num.precision > 38 || num.scale > num.precision)
			/* TODO add proper error */
			return SQL_ERROR;
		i = tds_numeric_bytes_per_prec[num.precision];
		memcpy(num.array + 1, sql_num->val, i - 1);
		tds_swap_bytes(num.array + 1, i - 1);
		if (i < sizeof(num.array))
			memset(num.array + i, 0, sizeof(num.array) - i);
		src = (char *) &num;
		break;
		/* TODO intervals */
	}

	dest = curcol->column_data;
	switch ((TDS_SERVER_TYPE) dest_type) {
	case SYBCHAR:
	case SYBVARCHAR:
	case XSYBCHAR:
	case XSYBVARCHAR:
		ores.cc.c = (TDS_CHAR*) dest;
		ores.cc.len = curcol->column_size;
		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_CHAR, &ores);
		if (res > curcol->column_size)
			res = curcol->column_size;
		break;
	case SYBBINARY:
	case SYBVARBINARY:
	case XSYBBINARY:
	case XSYBVARBINARY:
		ores.cb.ib = (TDS_CHAR*) dest;
		ores.cb.len = curcol->column_size;
		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_BINARY, &ores);
		if (res > curcol->column_size)
			res = curcol->column_size;
		break;
	case SYBTEXT:
	case SYBLONGBINARY:
	case SYBIMAGE:
		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, &ores);
		if (res < 0)
			return SQL_ERROR;
		blob = (TDSBLOB *) dest;
		free(blob->textvalue);
		blob->textvalue = ores.ib;
		break;
	case SYBNUMERIC:
	case SYBDECIMAL:
		((TDS_NUMERIC *) dest)->precision = drec_ipd->sql_desc_precision;
		((TDS_NUMERIC *) dest)->scale = drec_ipd->sql_desc_scale;
	case SYBINTN:
	case SYBINT1:
	case SYBINT2:
	case SYBINT4:
	case SYBINT8:
	case SYBFLT8:
	case SYBDATETIME:
	case SYBBIT:
	case SYBMONEY4:
	case SYBMONEY:
	case SYBDATETIME4:
	case SYBREAL:
	case SYBBITN:
	case SYBFLTN:
	case SYBMONEYN:
	case SYBDATETIMN:
	case SYBSINT1:
	case SYBUINT2:
	case SYBUINT4:
	case SYBUINT8:
	case SYBUNIQUE:
		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, (CONV_RESULT*) dest);
		break;
	default:
	case XSYBNVARCHAR:
	case XSYBNCHAR:
	case SYBNVARCHAR:
	case SYBNTEXT:
	case SYBVOID:
	case SYBVARIANT:
		/* TODO ODBC 3.5 */
		assert(0);
		res = -1;
		break;
	}

	if (res < 0)
		return SQL_ERROR;

	curcol->column_cur_size = res;

	return SQL_SUCCESS;
}
Esempio n. 15
0
/**
 * Convert parameters to libtds format
 * @return SQL_SUCCESS, SQL_ERROR or SQL_NEED_DATA
 */
SQLRETURN
odbc_sql2tds(TDS_STMT * stmt, const struct _drecord *drec_ipd, const struct _drecord *drec_apd, TDSCOLUMN *curcol,
	int compute_row, const TDS_DESC* axd, unsigned int n_row)
{
	TDS_DBC * dbc = stmt->dbc;
	TDSCONNECTION * conn = dbc->tds_socket->conn;
	int dest_type, src_type, sql_src_type, res;
	CONV_RESULT ores;
	TDSBLOB *blob;
	char *src, *converted_src;
	unsigned char *dest;
	int len;
	TDS_DATETIMEALL dta;
	TDS_NUMERIC num;
	SQL_NUMERIC_STRUCT *sql_num;
	SQLINTEGER sql_len;
	int need_data = 0, i;

	/* TODO handle bindings of char like "{d '2002-11-12'}" */
	tdsdump_log(TDS_DBG_INFO2, "type=%d\n", drec_ipd->sql_desc_concise_type);

	/* what type to convert ? */
	dest_type = odbc_sql_to_server_type(conn, drec_ipd->sql_desc_concise_type, drec_ipd->sql_desc_unsigned);
	if (!dest_type) {
		odbc_errs_add(&stmt->errs, "07006", NULL);	/* Restricted data type attribute violation */
		return SQL_ERROR;
	}
	tdsdump_log(TDS_DBG_INFO2, "trace\n");

	/* get C type */
	sql_src_type = drec_apd->sql_desc_concise_type;
	if (sql_src_type == SQL_C_DEFAULT)
		sql_src_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);

	/* TODO what happen for unicode types ?? */
	if (is_char_type(dest_type) && sql_src_type == SQL_C_WCHAR) {
		TDSICONV *conv = conn->char_convs[is_unicode_type(dest_type) ? client2ucs2 : client2server_chardata];

		tds_set_param_type(conn, curcol, dest_type);

                curcol->char_conv = tds_iconv_get(conn, odbc_get_wide_name(conn), conv->to.charset.name);
		memcpy(curcol->column_collation, conn->collation, sizeof(conn->collation));
	} else {
#ifdef ENABLE_ODBC_WIDE
		TDSICONV *conv = conn->char_convs[is_unicode_type(dest_type) ? client2ucs2 : client2server_chardata];

		tds_set_param_type(conn, curcol, dest_type);
		/* use binary format for binary to char */
		if (is_char_type(dest_type))
			curcol->char_conv = sql_src_type == SQL_C_BINARY ? NULL : tds_iconv_get(conn, tds_dstr_cstr(&dbc->original_charset), conv->to.charset.name);
#else
		tds_set_param_type(conn, curcol, dest_type);
		/* use binary format for binary to char */
		if (sql_src_type == SQL_C_BINARY && is_char_type(dest_type))
			curcol->char_conv = NULL;
#endif
	}
	if (is_numeric_type(curcol->column_type)) {
		curcol->column_prec = drec_ipd->sql_desc_precision;
		curcol->column_scale = drec_ipd->sql_desc_scale;
	}

	if (drec_ipd->sql_desc_parameter_type != SQL_PARAM_INPUT)
		curcol->column_output = 1;

	/* compute destination length */
	if (curcol->column_varint_size != 0) {
		/* curcol->column_size = drec_apd->sql_desc_octet_length; */
		/*
		 * TODO destination length should come from sql_desc_length, 
		 * however there is the encoding problem to take into account
		 * we should fill destination length after conversion keeping 
		 * attention to fill correctly blob/fixed type/variable type
		 */
		/* TODO location of this test is correct here ?? */
		if (dest_type != SYBUNIQUE && dest_type != SYBBITN && !is_fixed_type(dest_type)) {
			curcol->column_cur_size = 0;
			curcol->column_size = drec_ipd->sql_desc_length;
			if (curcol->column_size < 0) {
				curcol->on_server.column_size = curcol->column_size = 0x7FFFFFFFl;
			} else {
				if (is_unicode_type(dest_type))
					curcol->on_server.column_size = curcol->column_size * 2;
				else
					curcol->on_server.column_size = curcol->column_size;
			}
		}
	} else if (dest_type != SYBBIT) {
		/* TODO only a trick... */
		tds_set_param_type(conn, curcol, tds_get_null_type(dest_type));
	}

	/* test source type */
	/* TODO test intervals */
	src_type = odbc_c_to_server_type(sql_src_type);
	if (!src_type) {
		odbc_errs_add(&stmt->errs, "07006", NULL);	/* Restricted data type attribute violation */
		return SQL_ERROR;
	}

	/* we have no data to convert, just return */
	if (!compute_row)
		return SQL_SUCCESS;

	src = drec_apd->sql_desc_data_ptr;
	if (src && n_row) {
		SQLLEN len;
		if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
			len = axd->header.sql_desc_bind_type;
			if (axd->header.sql_desc_bind_offset_ptr)
				src += *axd->header.sql_desc_bind_offset_ptr;
		} else {
			len = odbc_get_octet_len(sql_src_type, drec_apd);
			if (len < 0)
				/* TODO sure ? what happen to upper layer ?? */
				/* TODO fill error */
				return SQL_ERROR;
		}
		src += len * n_row;
	}

	/* if only output assume input is NULL */
	if (drec_ipd->sql_desc_parameter_type == SQL_PARAM_OUTPUT) {
		sql_len = SQL_NULL_DATA;
	} else {
		sql_len = odbc_get_param_len(drec_apd, drec_ipd, axd, n_row);

		/* special case, MS ODBC handle conversion from "\0" to any to NULL, DBD::ODBC require it */
		if (src_type == SYBVARCHAR && sql_len == 1 && drec_ipd->sql_desc_parameter_type == SQL_PARAM_INPUT_OUTPUT
		    && src && *src == 0) {
			sql_len = SQL_NULL_DATA;
		}
	}

	/* compute source length */
	switch (sql_len) {
	case SQL_NULL_DATA:
		len = 0;
		break;
	case SQL_NTS:
		/* check that SQLBindParameter::ParameterValuePtr is not zero for input parameters */
		if (!src) {
			odbc_errs_add(&stmt->errs, "HY090", NULL);
			return SQL_ERROR;
		}
		if (sql_src_type == SQL_C_WCHAR)
			len = sqlwcslen((const SQLWCHAR *) src) * sizeof(SQLWCHAR);
		else
			len = strlen(src);
		break;
	case SQL_DEFAULT_PARAM:
		odbc_errs_add(&stmt->errs, "07S01", NULL);	/* Invalid use of default parameter */
		return SQL_ERROR;
		break;
	case SQL_DATA_AT_EXEC:
	default:
		len = sql_len;
		if (sql_len < 0) {
			/* test for SQL_C_CHAR/SQL_C_BINARY */
			switch (sql_src_type) {
			case SQL_C_CHAR:
			case SQL_C_WCHAR:
			case SQL_C_BINARY:
				break;
			default:
				odbc_errs_add(&stmt->errs, "HY090", NULL);
				return SQL_ERROR;
			}
			len = SQL_LEN_DATA_AT_EXEC(sql_len);
			need_data = 1;

			/* dynamic length allowed only for BLOB fields */
			switch (drec_ipd->sql_desc_concise_type) {
			case SQL_LONGVARCHAR:
			case SQL_WLONGVARCHAR:
			case SQL_LONGVARBINARY:
				break;
			default:
				odbc_errs_add(&stmt->errs, "HY090", NULL);
				return SQL_ERROR;
			}
		}
	}

	/* set NULL. For NULLs we don't need to allocate row buffer so avoid it */
	if (!need_data) {
		assert(drec_ipd->sql_desc_parameter_type != SQL_PARAM_OUTPUT || sql_len == SQL_NULL_DATA);
		if (sql_len == SQL_NULL_DATA) {
			curcol->column_cur_size = -1;
			return SQL_SUCCESS;
		}
	}

	switch (dest_type) {
	case SYBCHAR:
	case SYBVARCHAR:
	case XSYBCHAR:
	case XSYBVARCHAR:
	case XSYBNVARCHAR:
	case XSYBNCHAR:
	case SYBNVARCHAR:
	case SYBNTEXT:
	case SYBTEXT:
		if (!need_data && (sql_src_type == SQL_C_CHAR || sql_src_type == SQL_C_WCHAR || sql_src_type == SQL_C_BINARY)) {
			if (curcol->column_data && curcol->column_data_free)
				curcol->column_data_free(curcol);
			curcol->column_data_free = NULL;
			if (is_blob_col(curcol)) {
				/* trick to set blob without freeing it, _odbc_blob_free does not free TDSBLOB->textvalue */
				TDSBLOB *blob = (TDSBLOB *) calloc(1, sizeof(TDSBLOB));
				if (!blob) {
					odbc_errs_add(&stmt->errs, "HY001", NULL);
					return SQL_ERROR;
				}
				blob->textvalue = src;
				curcol->column_data = (TDS_UCHAR*) blob;
				curcol->column_data_free = _odbc_blob_free;
			} else {
				curcol->column_data = (TDS_UCHAR*) src;
			}
			curcol->column_size = len;
			curcol->column_cur_size = len;
			return SQL_SUCCESS;
		}
	}

	/* allocate given space */
	if (!tds_alloc_param_data(curcol)) {
		odbc_errs_add(&stmt->errs, "HY001", NULL);
		return SQL_ERROR;
	}

	/* fill data with SQLPutData */
	if (need_data) {
		curcol->column_cur_size = 0;
		return SQL_NEED_DATA;
	}

	if (!src) {
		odbc_errs_add(&stmt->errs, "HY090", NULL);
		return SQL_ERROR;
	}

	/* convert special parameters (not libTDS compatible) */
	switch (src_type) {
	case SYBMSDATETIME2:
		convert_datetime2server(drec_apd->sql_desc_concise_type, src, &dta);
		src = (char *) &dta;
		break;
	case SYBDECIMAL:
	case SYBNUMERIC:
		sql_num = (SQL_NUMERIC_STRUCT *) src;
		num.precision = sql_num->precision;
		num.scale = sql_num->scale;
		num.array[0] = sql_num->sign ^ 1;
		/* test precision so client do not crash our library */
		if (num.precision <= 0 || num.precision > 38 || num.scale > num.precision)
			/* TODO add proper error */
			return SQL_ERROR;
		i = tds_numeric_bytes_per_prec[num.precision];
		memcpy(num.array + 1, sql_num->val, i - 1);
		tds_swap_bytes(num.array + 1, i - 1);
		if (i < sizeof(num.array))
			memset(num.array + i, 0, sizeof(num.array) - i);
		src = (char *) &num;
		break;
		/* TODO intervals */
	}

	converted_src = NULL;
	if (sql_src_type == SQL_C_WCHAR) {
		converted_src = src = odbc_wstr2str(stmt, src, &len);
		if (!src)
			return SQL_ERROR;
		src_type = SYBVARCHAR;
	}

	dest = curcol->column_data;
	switch ((TDS_SERVER_TYPE) dest_type) {
	case SYBCHAR:
	case SYBVARCHAR:
	case XSYBCHAR:
	case XSYBVARCHAR:
	case XSYBNVARCHAR:
	case XSYBNCHAR:
	case SYBNVARCHAR:
		ores.cc.c = (TDS_CHAR*) dest;
		ores.cc.len = curcol->column_size;
		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_CHAR, &ores);
		if (res > curcol->column_size)
			res = curcol->column_size;
		break;
	case SYBBINARY:
	case SYBVARBINARY:
	case XSYBBINARY:
	case XSYBVARBINARY:
		ores.cb.ib = (TDS_CHAR*) dest;
		ores.cb.len = curcol->column_size;
		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_BINARY, &ores);
		if (res > curcol->column_size)
			res = curcol->column_size;
		break;
	case SYBNTEXT:
		dest_type = SYBTEXT;
	case SYBTEXT:
	case SYBLONGBINARY:
	case SYBIMAGE:
		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, &ores);
		if (res >= 0) {
			blob = (TDSBLOB *) dest;
			free(blob->textvalue);
			blob->textvalue = ores.ib;
		}
		break;
	case SYBNUMERIC:
	case SYBDECIMAL:
		((TDS_NUMERIC *) dest)->precision = drec_ipd->sql_desc_precision;
		((TDS_NUMERIC *) dest)->scale = drec_ipd->sql_desc_scale;
	case SYBINTN:
	case SYBINT1:
	case SYBINT2:
	case SYBINT4:
	case SYBINT8:
	case SYBFLT8:
	case SYBDATETIME:
	case SYBBIT:
	case SYBMONEY4:
	case SYBMONEY:
	case SYBDATETIME4:
	case SYBREAL:
	case SYBBITN:
	case SYBFLTN:
	case SYBMONEYN:
	case SYBDATETIMN:
	case SYBSINT1:
	case SYBUINT2:
	case SYBUINT4:
	case SYBUINT8:
	case SYBUNIQUE:
	case SYBMSTIME:
	case SYBMSDATE:
	case SYBMSDATETIME2:
	case SYBMSDATETIMEOFFSET:
		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, (CONV_RESULT*) dest);
		break;
	default:
	case SYBVOID:
	case SYBVARIANT:
		/* TODO ODBC 3.5 */
		assert(0);
		res = -1;
		break;
	}

	free(converted_src);
	if (res < 0) {
		odbc_convert_err_set(&stmt->errs, res);
		return SQL_ERROR;
	}

	curcol->column_cur_size = res;

	return SQL_SUCCESS;
}
Esempio n. 16
0
void
sql_blobInsert(const char *tabname, const char *colname, int rowid,
   const char *filename, void *offset, int length)
{
    char blobcmd[100];
    SQLINTEGER output_length;
    bool isfile;
    int fd;

    /* basic sanity checks */
    checkConnect();
    if(isnullstring(tabname))
	errorPrint("2blobInsert, null table name");
    if(isnullstring(colname))
	errorPrint("2blobInsert, null column name");
    if(rowid <= 0)
	errorPrint("2invalid rowid in blobInsert");
    if(length < 0)
	errorPrint("2invalid length in blobInsert");
    if(strlen(tabname) + strlen(colname) + 42 >= sizeof (blobcmd))
	errorPrint("@internal blobInsert command too long");

    isfile = true;
    if(isnullstring(filename)) {
	isfile = false;
	if(!offset)
	    errorPrint("2blobInsert is given null filename and null buffer");
    } else {
	offset = blobbuf;
	fd = eopen(filename, O_RDONLY | O_BINARY, 0);
	length = fileSizeByHandle(fd);
	if(length == 0) {
	    isfile = false;
	    close(fd);
	}
    }

    /* set up the blob insert command, using one host variable */
    sprintf(blobcmd, "update %s set %s = %s where rowid = %d",
       tabname, colname, (length ? "?" : "NULL"), rowid);
    stmt_text = blobcmd;
    debugStatement();
    newStatement();
    rv_lastNrows = 0;

    output_length = length;
    rc = SQL_SUCCESS;
    if(isfile) {
	output_length = SQL_LEN_DATA_AT_EXEC(length);
	rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
	   SQL_C_BINARY, SQL_LONGVARCHAR, length, 0,
	   blobcmd, length, &output_length);
	if(rc)
	    close(fd);
    } else if(length) {
	rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
	   SQL_C_BINARY, SQL_LONGVARCHAR, length, 0,
	   offset, length, &output_length);
    }
    if(errorTrap(0)) {
	SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
	return;
    }

    rc = SQLExecDirect(hstmt, blobcmd, SQL_NTS);
    SQLRowCount(hstmt, &rv_lastNrows);

    if(isfile) {
	if(rc != SQL_NEED_DATA) {
	    close(fd);
	    if(rc == SQL_SUCCESS)
		errorPrint("@blobInsert expected SQL_NEED_DATA");
	    errorTrap(0);
	    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
	    return;
	}

	output_length = 0;
	rc = SQLParamData(hstmt, (void **)&output_length);
	if((char *)output_length != blobcmd) {
	    close(fd);
	    errorPrint("2blobInsert got bad key from SQLParamData");
	}

	lseek(fd, 0L, 0);
	while(length) {
	    int n = length;
	    if(n > sizeof (blobbuf))
		n = sizeof (blobbuf);
	    if(read(fd, blobbuf, n) != n) {
		close(fd);
		errorPrint("2cannot read file %s, errno %d", filename, errno);
	    }
	    length -= n;

	    rc = SQLPutData(hstmt, blobbuf, n);
	    if(rc) {
		close(fd);
		errorTrap(0);
		SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
		return;
	    }
	}			/* loop reading the file */

	close(fd);

	/* since there are no more exec-time parameters,
	 * this call completes the execution of the SQL statement. */
	rc = SQLParamData(hstmt, (void **)&output_length);
    }

    if(errorTrap(0)) {
	SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
	return;
    }

    if(sql_debug)
	appendFile(sql_debuglog, "%d rows affected", rv_lastNrows);
    if(sql_debug2)
	printf("%d rows affected\n", rv_lastNrows);
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    exclist = 0;
}				/* sql_blobInsert */