C component methods return row results using the routines listed in Chapter 5, “C Routines Reference,” in the EAServer API Reference.
This section describes the two different algorithms for returning results sets from C components:
“Forwarding a result set with JagResultsPassthrough” describes how to forward an ODBC or Client-Library result set to the client. Use this method when you want to send query results as-is.
“Sending results row-by-row” describes the sequence of calls to define a result set’s columns and send the result set row-by-row. Use this method when you must manufacture a result set from scratch. You can also use this method to filter rows or columns from the results of a remote-database query.
You cannot call C routines to send a result set unless
the IDL definition of the component method returns TabularResults::ResultSet or TabularResults::ResultSets.
To return result sets from C++ components:
C++ component methods that return a single result set are defined to return a pointer to a TabularResults::ResultSet structure; use the C routines to return a single result set, as described in “Sending results row-by-row”, then return NULL in place of the structure pointer.
C++ component methods that return multiple result sets must populate an array of TabularResults::ResultSet structures. For more information, see the generated IDL documentation for TabularResults::ResultSet under html/ir/index.html in your EAServer installation.
In your C or C++ component, you can call JagResultsPassthrough after you have sent a remote-database query with ODBC or Client-Library calls. JagResultsPassthrough extracts the results from a Client-Library or ODBC control structure and forwards them to the client. For details, see Chapter 5, “C Routines Reference” in the EAServer API Reference.
The steps below describe the call sequence for sending a result set from scratch.
Call JagBeginResults, specifying the number of columns in the result set.
For each column, call JagDescribeCol to describe the name, datatype, and size of the column.
JagDescribeCol accepts either ODBC or Client-Library datatypes. If you use ODBC datatypes, and the column represents money, call JagColAttributes to set the column’s SQL_COLUMN_MONEY attribute.
This step and the next step may be combined; you can describe columns and bind them in the same loop.
For each column, call JagBindCol, specifying the locations of variables where the column’s data values and lengths can be read.
For each row, update the variables containing the column’s data value and length, then call JagSendData to send the row to the client.
Call JagEndResults to indicate that all rows have been sent.
The example code below defines a method that returns a result set, using ODBC datatypes to describe the columns:
#define LOG_ERROR(errtext) (CS_VOID)JagLog(JAG_TRUE,\ "sendrows_C: rows1(): " errtext “\n”) #define MAX_STRCOL 64 /* ** Component - sendrows_C ** Method - rows1 ** ** Return a small result set to the client. ** */ CS_RETCODE rows1( ) { JagStatus jsret; SQLINTEGER intcol; SQLINTEGER intcol_len = sizeof(SQLINTEGER); SQLSMALLINT intcol_ind = 0; SQLCHAR strcol[MAX_STRCOL + 1]; SQLINTEGER strcol_len; SQLSMALLINT strcol_ind = 0; SDOUBLE doublecol; SQLINTEGER doublecol_len = sizeof(SDOUBLE); SQLSMALLINT doublecol_ind = 0; SQLINTEGER rowcount = 0; /* ** Step 1: JagBeginResults() to begin sending ** a new result set. Number of columns is 3. */ jsret = JagBeginResults(3); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagBeginResults() failed."); return CS_FAIL; } /* ** Steps 2 and 3: For each column, describe the ** column’s metadata and bind the column to a ** variable from which values will be ** read. */ /* ** First column is integer, bound to int_col. */ jsret = JagDescribeCol(1, JAG_ODBC_TYPE, "First", SQL_INTEGER, sizeof(SDWORD), 0, 0, SQL_NULLABLE); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagDescribeCol(1) failed."); return CS_FAIL; } intcol_len = sizeof(SDWORD); jsret = JagBindCol(1, JAG_ODBC_TYPE, SQL_C_SLONG, &intcol, intcol_len, &intcol_len, &intcol_ind); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagBindCol(1) failed."); return CS_FAIL; } /* ** Second column is a string, bound to string_col. */ jsret = JagDescribeCol(2, SQL_VARCHAR, "Second", MAX_STRCOL, 0, 0, SQL_NULLABLE); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagDescribeCol(2) failed."); return CS_FAIL; } /* ** Length specified as MAX_STRCOL + 1 to ** allow space for null-terminator. */ jsret = JagBindCol(2, SQL_C_CHAR, &strcol, MAX_STRCOL + 1, &strcol_len, &strcol_ind); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagBindCol(2) failed."); return CS_FAIL; } /* ** Third column is a SQL_DOUBLE, bound to double_col. ** It does not allow nulls. */ jsret = JagDescribeCol(3, SQL_DOUBLE, "Third", sizeof(SDOUBLE), 0, 0, SQL_NO_NULLS); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagDescribeCol(3) failed."); return CS_FAIL; } doublecol_ind = sizeof(SDOUBLE); jsret = JagBindCol(3, SQL_C_DOUBLE, &doublecol, doublecol_ind, &doublecol_len, &doublecol_ind); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagBindCol(3) failed."); return CS_FAIL; } /* ** Step 4: send the rows. */ /* ** Values for row 1: ** 1, "Uno", 1.001 */ ++rowcount; intcol = 1; strcpy(strcol, "Uno"); strcol_ind = strlen(strcol); doublecol = 1.001; jsret = JagSendData(); /* ** Values for row 2: ** 2, "Dos", 2.002 */ ++rowcount; intcol = 2; strcpy(strcol, "Dos"); strcol_ind = strlen(strcol); doublecol = 2.002; jsret = JagSendData(); /* ** Values for row 2: ** 3, "Tres", 3.003 */ ++rowcount; intcol = 3; strcpy(strcol, "Tres"); strcol_ind = strlen(strcol); doublecol = 3.003; jsret = JagSendData(); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagSendData(1) failed."); return CS_FAIL; } /* ** Step 5: Call JagEndResults() to say that we’re done. */ jsret = JagEndResults(rowcount); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagEndResults() failed."); return CS_FAIL; } return(CS_SUCCEED); }
The example code below defines a method that returns a result set, using Client-Library datatypes to describe the columns:
#include <jagpublic.h> #include <ctpublic.h> CS_RETCODE JAG_PUBLIC getResultSet (void { JagStatus jsret; CS_SMALLINT intcol_ind = 0; CS_INT intcol_len = sizeof (CS_INT) ; CS_INT intcol = 0 ; CS_CHAR strcol[MAX_STRCOL + 1]; CS_INT strcol_len = 0; CS_INT strcol_ind = 0; char *data[] = {"one", "two", "three", "for", "five", "six", "seven", "eight", "nine", "ten"} ; /* ** Step 1: JagBeginResults() to begin sending ** a new result set. Number of columns is 2 */ jsret = JagBeginResults(2); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagBeginResults() failed."); return CS_FAIL; } /* type int column*/ jsret = JagDescribeCol(1, JAG_CS_TYPE, "Int Column", CS_INT_TYPE, sizeof ( CS_INT) , 0, 0, CS_CANBENULL); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagDescribeCol(2) failed."); return CS_FAIL; } /*A columm of type string*/ jsret = JagDescribeCol(2, JAG_CS_TYPE, "StringColumn", CS_CHAR_TYPE, MAX_STRCOL, 0, 0, CS_CANBENULL); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagDescribeCol(2) failed."); return CS_FAIL; } jsret = JagBindCol(1, JAG_CS_TYPE , CS_INT_TYPE , &intcol , intcol_len, &intcol_len, &intcol_ind ); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagBindCol(2) failed."); return CS_FAIL ; } jsret = JagBindCol(2, JAG_CS_TYPE , CS_CHAR_TYPE , strcol , MAX_STRCOL, &strcol_ind , (CS_SMALLINT*)NULL); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagBindCol(2) failed."); return CS_FAIL ; } /* ** Step 4: send the rows. */ /* ** Values to send */ for (int jj = 0 ; jj < MAXDATA ; jj++) { intcol = jj + 1 ; strcpy((char*)strcol, data[jj] ); strcol_ind = strlen((char*)strcol) ; jsret = JagSendData(); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagSendData(1) failed."); return CS_FAIL; } } /* ** Step 5: Call JagEndResults() to say that we're done. */ jsret = JagEndResults( MAXDATA ); if (jsret != JAG_SUCCEED) { LOG_ERROR("JagEndResults() failed."); return CS_FAIL; } return CS_SUCCEED; }
Copyright © 2005. Sybase Inc. All rights reserved. |
![]() |