Esempio n. 1
0
// FIXME: use ct_setparam to avoid copying data
void command::set_params(sybase_query &query, const QoreListNode *args, ExceptionSink *xsink) {
   unsigned nparams = query.param_list.size();

   for (unsigned i = 0; i < nparams; ++i) {
      if (query.param_list[i] == 'd')
	 continue;

      const AbstractQoreNode *val = args ? args->retrieve_entry(i) : NULL;

      CS_DATAFMT datafmt;
      memset(&datafmt, 0, sizeof(datafmt));
      datafmt.status = CS_INPUTVALUE;
      datafmt.namelen = CS_NULLTERM;
      sprintf(datafmt.name, "@par%d", int(i + 1));
      datafmt.maxlength = CS_UNUSED;
      datafmt.count = 1;

      CS_RETCODE err = CS_FAIL;

      if (!val || is_null(val) || is_nothing(val)) {
#ifdef FREETDS
	 // it seems to be necessary to specify a type like
	 // this to get a null value to be bound with freetds
	 datafmt.datatype = CS_CHAR_TYPE;
	 datafmt.format = CS_FMT_NULLTERM;
	 datafmt.maxlength = 1;
#endif
	 // SQL NULL value
	 err = ct_param(m_cmd, &datafmt, 0, CS_UNUSED, -1);
	 if (err != CS_SUCCEED) {
	    m_conn.do_exception(xsink, "DBI:SYBASE:EXEC-ERROR",
				"ct_param() for 'null' failed for parameter %u with error %d",
				i, (int)err);
	    return;
	 }
	 continue;
      }

      qore_type_t ntype = val ? val->getType() : 0;

      switch (ntype) {
	 case NT_STRING: {
	    const QoreStringNode *str = reinterpret_cast<const QoreStringNode *>(val);
	    // ensure we bind with the proper encoding for the connection
	    TempEncodingHelper s(str, m_conn.getEncoding(), xsink);
	    if (!s) throw ss::Error("DBI:SYBASE:EXEC-ERROR", "encoding");

	    int slen = s->strlen();
	    datafmt.datatype = CS_CHAR_TYPE;
	    datafmt.format = CS_FMT_NULLTERM;
	    // NOTE: setting large sizes here like 2GB works for sybase ctlib,
	    // not for freetds
	    datafmt.maxlength = slen + 1;
	    err = ct_param(m_cmd, &datafmt, (CS_VOID*)s->getBuffer(), slen, 0);
	    break;
	 }

	 case NT_NUMBER: {
	    QoreStringValueHelper vh(val);
	    int slen = vh->strlen();
	    datafmt.datatype = CS_CHAR_TYPE;
	    datafmt.format = CS_FMT_NULLTERM;
	    datafmt.maxlength = slen + 1;
	    err = ct_param(m_cmd, &datafmt, (CS_VOID *)vh->getBuffer(), slen, 0);
	    break;
	 }

	 case NT_DATE: {
	    const DateTimeNode *date = reinterpret_cast<const DateTimeNode *>(val);
	    CS_DATETIME dt;
	    ss::Conversions conv;
	    if (conv.DateTime_to_DATETIME(date, dt, xsink))
	       throw ss::Error("DBI:SYBASE:EXEC-ERROR", "can't convert date");

	    datafmt.datatype = CS_DATETIME_TYPE;
	    err = ct_param(m_cmd, &datafmt, &dt, sizeof(dt), 0);
	    break;
	 }

	 case NT_INT: {
#ifdef CS_BIGINT_TYPE
	    datafmt.datatype = CS_BIGINT_TYPE;
	    err = ct_param(m_cmd, &datafmt, &(const_cast<QoreBigIntNode *>(reinterpret_cast<const QoreBigIntNode *>(val))->val), sizeof(int64), 0);
#else
	    int64 ival = reinterpret_cast<const QoreBigIntNode *>(val)->val;
	    // if it's a 32-bit integer, bind as integer
	    if (ival <= 2147483647 && ival >= -2147483647) {
	       datafmt.datatype = CS_INT_TYPE;
	       CS_INT vint = ival;
	       err = ct_param(m_cmd, &datafmt, &vint, sizeof(CS_INT), 0);
	    }
	    else { // bind as float
	       CS_FLOAT fval = ival;
	       datafmt.datatype = CS_FLOAT_TYPE;
	       err = ct_param(m_cmd, &datafmt, &fval, sizeof(CS_FLOAT), 0);
	    }
#endif
	    break;
	 }

	 case NT_BOOLEAN: {
	    // Seems mssql doesn't like  CS_BIT_TYPE for some reason.
	    // Replacing by CS_INT_TYPE helps
	    //
	    // The "BIT" code is supposed to be like this:
	    // datafmt.datatype = CS_BIT_TYPE;
	    // err = ct_param(m_cmd, &datafmt, &bval, sizeof(bval), 0);
	    // ... but it doesn't work

	    CS_BIT bval = reinterpret_cast<const QoreBoolNode *>(val)->getValue();
	    datafmt.datatype = CS_INT_TYPE;
	    int64 ival = bval ? 1 : 0;
	    err = ct_param(m_cmd, &datafmt, &ival, sizeof(ival), 0);
	    break;
	 }

	 case NT_FLOAT: {
	    CS_FLOAT fval = reinterpret_cast<const QoreFloatNode *>(val)->f;
	    datafmt.datatype = CS_FLOAT_TYPE;
	    err = ct_param(m_cmd, &datafmt, &fval, sizeof(CS_FLOAT), 0);
	    break;
	 }

	 case NT_BINARY: {
	    const BinaryNode *b = reinterpret_cast<const BinaryNode *>(val);
	    datafmt.datatype = CS_BINARY_TYPE;
	    datafmt.maxlength = b->size();
	    datafmt.count = 1;
	    err = ct_param(m_cmd, &datafmt, (void *)b->getPtr(), b->size(), 0);
	    break;
	 }

	 default:
	    m_conn.do_exception(xsink, "DBI:SYBASE:BIND-ERROR",
				"do not know how to bind values of type '%s'",
				val->getTypeName());
	    return;
      } // switch(ntype)

      if (err != CS_SUCCEED) {
	 m_conn.do_exception(xsink, "DBI:SYBASE:EXEC-ERROR",
			     "ct_param() for binary parameter %u failed with error",
			     i, (int)err);
      }
   }
}
Esempio n. 2
0
static PyObject *CS_COMMAND_ct_param(CS_COMMANDObj *self, PyObject *args)
{
    PyObject *obj;
    CS_RETCODE status;

    if (!PyArg_ParseTuple(args, "O", &obj))
	return NULL;

    if (self->cmd == NULL) {
	PyErr_SetString(PyExc_TypeError, "CS_COMMAND has been dropped");
	return NULL;
    }

    /* FIXME: Need to handle CS_UPDATECOL variant */
    if (DataBuf_Check(obj)) {
	DataBufObj *databuf = (DataBufObj *)obj;

	/* PyErr_Clear(); */

	SY_CONN_BEGIN_THREADS(self->conn);
	status = ct_param(self->cmd, &databuf->fmt,
			  databuf->buff, databuf->copied[0],
			  databuf->indicator[0]);
	SY_CONN_END_THREADS(self->conn);

	if (self->debug) {
	    debug_msg("ct_param(cmd%d, &databuf%d->fmt=",
		      self->serial, databuf->serial);
	    datafmt_debug(&databuf->fmt);
	    debug_msg(", databuf%d->buff, %d, %d) -> %s\n",
		      databuf->serial,
		      (int)databuf->copied[0], databuf->indicator[0],
		      value_str(VAL_STATUS, status));
	}
	if (PyErr_Occurred())
	    return NULL;
    } else if (CS_DATAFMT_Check(obj)) {
	CS_DATAFMTObj *datafmt = (CS_DATAFMTObj *)obj;

	/* PyErr_Clear(); */

	SY_CONN_BEGIN_THREADS(self->conn);
	status = ct_param(self->cmd, &datafmt->fmt,
			  NULL, CS_UNUSED, (CS_SMALLINT)CS_UNUSED);
	SY_CONN_END_THREADS(self->conn);

	if (self->debug) {
	    debug_msg("ct_param(cmd%d, &fmt=", self->serial);
	    datafmt_debug(&datafmt->fmt);
	    debug_msg(", NULL, CS_UNUSED, CS_UNUSED) -> %s\n",
		      value_str(VAL_STATUS, status));
	}
	if (PyErr_Occurred())
	    return NULL;
    } else {
	PyErr_SetString(PyExc_TypeError, "expect CS_DATAFMT or DataBuf");
	return NULL;
	
    }
    return PyInt_FromLong(status);
}
Esempio n. 3
0
static int 
insert_test(CS_CONNECTION *conn, CS_COMMAND *cmd, int useNames)
{
	CS_CONTEXT *ctx;

	CS_RETCODE ret;
	CS_INT res_type;

	CS_DATAFMT datafmt;
	CS_DATAFMT srcfmt;
	CS_DATAFMT destfmt;
	CS_INT intvar;
	CS_FLOAT floatvar;
	CS_MONEY moneyvar;
	CS_DATEREC datevar;
	char moneystring[10];
	char dummy_name[30];
	char dummy_name2[20];
	CS_INT destlen;

	/* clear table */
	run_command(cmd, "delete #ctparam_lang");

	/*
	 * Assign values to the variables used for parameter passing.
	 */

	intvar = 2;
	floatvar = 0.12;
	strcpy(dummy_name, "joe blow");
	strcpy(dummy_name2, "");
	strcpy(moneystring, "300.90");

	/*
	 * Clear and setup the CS_DATAFMT structures used to convert datatypes.
	 */

	memset(&srcfmt, 0, sizeof(CS_DATAFMT));
	srcfmt.datatype = CS_CHAR_TYPE;
    srcfmt.maxlength = (CS_INT)strlen(moneystring);
	srcfmt.precision = 5;
	srcfmt.scale = 2;
	srcfmt.locale = NULL;

	memset(&destfmt, 0, sizeof(CS_DATAFMT));
	destfmt.datatype = CS_MONEY_TYPE;
	destfmt.maxlength = sizeof(CS_MONEY);
	destfmt.precision = 5;
	destfmt.scale = 2;
	destfmt.locale = NULL;

	/*
	 * Convert the string representing the money value
	 * to a CS_MONEY variable. Since this routine does not have the
	 * context handle, we use the property functions to get it.
	 */
	if ((ret = ct_cmd_props(cmd, CS_GET, CS_PARENT_HANDLE, &conn, CS_UNUSED, NULL)) != CS_SUCCEED) {
		fprintf(stderr, "ct_cmd_props() failed\n");
		return 1;
	}
	if ((ret = ct_con_props(conn, CS_GET, CS_PARENT_HANDLE, &ctx, CS_UNUSED, NULL)) != CS_SUCCEED) {
		fprintf(stderr, "ct_con_props() failed\n");
		return 1;
	}
	ret = cs_convert(ctx, &srcfmt, (CS_VOID *) moneystring, &destfmt, &moneyvar, &destlen);
	if (ret != CS_SUCCEED) {
		fprintf(stderr, "cs_convert() failed\n");
		return 1;
	}

	/*
	 * create the command
	 */
    if ((ret = ct_command(cmd, CS_LANG_CMD, query, (CS_INT)strlen(query),
		CS_UNUSED)) != CS_SUCCEED) 
	{
		fprintf(stderr, "ct_command(CS_LANG_CMD) failed\n");
		return 1;
	}

	/*
	 * Clear and setup the CS_DATAFMT structure, then pass
	 * each of the parameters for the query.
	 */
	memset(&datafmt, 0, sizeof(datafmt));
	if (useNames)
		strcpy(datafmt.name, "@in1");
	else
		datafmt.name[0] = 0;
	datafmt.maxlength = 255;
	datafmt.namelen = CS_NULLTERM;
	datafmt.datatype = CS_CHAR_TYPE;
	datafmt.status = CS_INPUTVALUE;

	/*
	 * The character string variable is filled in by the RPC so pass NULL
	 * for the data 0 for data length, and -1 for the indicator arguments.
	 */
    ret = ct_param(cmd, &datafmt, dummy_name, (CS_INT)strlen(dummy_name), 0);
	if (CS_SUCCEED != ret) {
		fprintf(stderr, "ct_param(char) failed\n");
		return 1;
	}

	if (useNames)
		strcpy(datafmt.name, "@in2");
	else
		datafmt.name[0] = 0;
	datafmt.maxlength = 255;
	datafmt.namelen = CS_NULLTERM;
	datafmt.datatype = CS_CHAR_TYPE;
	datafmt.status = CS_INPUTVALUE;

    ret = ct_param(cmd, &datafmt, dummy_name2, (CS_INT)strlen(dummy_name2), 0);
	if (CS_SUCCEED != ret) {
		fprintf(stderr, "ct_param(char) failed\n");
		return 1;
	}

	if (useNames)
		strcpy(datafmt.name, "@in3");
	else
		datafmt.name[0] = 0;
	datafmt.namelen = CS_NULLTERM;
	datafmt.datatype = CS_INT_TYPE;
	datafmt.status = CS_INPUTVALUE;

	ret = ct_param(cmd, &datafmt, (CS_VOID *) & intvar, CS_SIZEOF(CS_INT), 0);
	if (CS_SUCCEED != ret) {
		fprintf(stderr, "ct_param(int) failed\n");
		return 1;
	}

	if (useNames)
		strcpy(datafmt.name, "@moneyval");
	else
		datafmt.name[0] = 0;
	datafmt.namelen = CS_NULLTERM;
	datafmt.datatype = CS_MONEY_TYPE;
	datafmt.status = CS_INPUTVALUE;

	ret = ct_param(cmd, &datafmt, (CS_VOID *) & moneyvar, CS_SIZEOF(CS_MONEY), 0);
	if (CS_SUCCEED != ret) {
		fprintf(stderr, "ct_param(money) failed\n");
		return 1;
	}

	if (useNames)
		strcpy(datafmt.name, "@dateval");
	else
		datafmt.name[0] = 0;
	datafmt.namelen = CS_NULLTERM;
	datafmt.datatype = CS_DATETIME_TYPE;
	datafmt.status = CS_INPUTVALUE;
	memset(&datevar, 0, sizeof(CS_DATEREC));
	datevar.dateyear = 2003;
	datevar.datemonth = 2;
	datevar.datedmonth = 1;

	ret = ct_param(cmd, &datafmt, &datevar, 0, 0);
	if (CS_SUCCEED != ret) {
		fprintf(stderr, "ct_param(datetime) failed");
		return 1;
	}

	if (useNames)
		strcpy(datafmt.name, "@floatval");
	else
		datafmt.name[0] = 0;
	datafmt.namelen = CS_NULLTERM;
	datafmt.datatype = CS_FLOAT_TYPE;
	datafmt.status = CS_INPUTVALUE;

	ret = ct_param(cmd, &datafmt, &floatvar, 0, 0);
	if (CS_SUCCEED != ret) {
		fprintf(stderr, "ct_param(float) failed");
		return 1;
	}

	/*
	 * Send the command to the server
	 */
	if (ct_send(cmd) != CS_SUCCEED) {
		fprintf(stderr, "ct_send(CS_LANG_CMD) failed\n");
		return 1;
	}

	/*
	 * Process the results.
	 */
	while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
		switch ((int) res_type) {

		case CS_CMD_SUCCEED:
		case CS_CMD_DONE:
			{
				CS_INT rowsAffected=0;
				ct_res_info(cmd, CS_ROW_COUNT, &rowsAffected, CS_UNUSED, NULL);
				if (1 != rowsAffected) 
					fprintf(stderr, "insert touched %d rows instead of 1\n", rowsAffected);
			}
			break;

		case CS_CMD_FAIL:
			/*
			 * The server encountered an error while
			 * processing our command.
			 */
			fprintf(stderr, "ct_results returned CS_CMD_FAIL.\n");
			break;

		case CS_STATUS_RESULT:
			/*
			 * The server encountered an error while
			 * processing our command.
			 */
			fprintf(stderr, "ct_results returned CS_STATUS_RESULT.\n");
			break;

		default:
			/*
			 * We got something unexpected.
			 */
			fprintf(stderr, "ct_results returned unexpected result type %d\n", res_type);
			return 1;
		}
	}
	if (ret != CS_END_RESULTS)
		fprintf(stderr, "ct_results returned unexpected result %d.\n", (int) ret);

	/* test row inserted */
	ret = run_command(cmd, "if not exists(select * from #ctparam_lang where name = 'joe blow' and name2 is not null and age = 2) select 1");
	if (ret != CS_SUCCEED) {
		fprintf(stderr, "check row inserted failed\n");
		exit(1);
	}

	return 0;
}