SQLFetch after Insert statement using UnixODBC - odbc

I've been doing some scripting tests with a SAP Hana database, and am currently trying to pass to it a query, and have it execute in the database, and validate the results with DBeaver. Except when I execute an INSERT query, SQLFetch keeps looping infinitely.
My C code is as follows:
int main()
{
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLRETURN ret; /* ODBC API return status */
SQLSMALLINT columns, rows; /* number of columns in result-set */
SQLCHAR outstr[1024];
SQLSMALLINT outstrlen;
int row = 0;
columns = 0;
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
ret = SQLDriverConnect(dbc, NULL, "driver=/usr/lib/libodbcHDB32.so;servernode=hana.tests.com:39015;UID=TESTDB;PWD=abc123", SQL_NTS,
outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);
if (SQL_SUCCEEDED(ret)) {
printf("Connected\n");
printf("Returned connection string was:\n\t%s\n", outstr);
} else {
fprintf(stderr, "Failed to connect\n");
return -1;
}
/* Allocate a statement handle */
SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
/* Retrieve a list of tables */
SQLExecDirect(stmt, "INSERT INTO NEWTABLE VALUES ('test123');", SQL_NTS);
/* How many columns are there */
SQLNumResultCols(stmt, &columns);
fprintf(stderr, "Number of columns: %d\n", columns);
/* Loop through the rows in the result-set */
while ((ret = SQLFetch(stmt)) == SQL_SUCCESS) {
SQLUSMALLINT i;
printf("Row %d\n", row++);
/* Loop through the columns */
for (i = 1; i <= columns; i++) {
SQLINTEGER indicator;
char buf[512];
/* retrieve column data as a string */
ret = SQLGetData(stmt, i, SQL_C_CHAR,
buf, sizeof(buf), &indicator);
if (SQL_SUCCEEDED(ret)) {
/* Handle null columns */
if (indicator == SQL_NULL_DATA) strcpy(buf, "NULL");
printf(" Column %u : %s\n", i, buf);
}
}
}
return 0;
}
In the output the code keeps printing:
Number of columns: 0
Row 0
Row 1
Row 2
Row 3
Row 4
...
And so on... SQLFetch always seems to return SQL_SUCCESS. Am I missing some configuration step that prevents this behavior? I expected that if the statement was INSERT either SQLFetch would return something other than SQL_SUCCESS.
I mainly guided myself through this tutorial https://www.easysoft.com/developer/languages/c/odbc_tutorial.html#basic_fetch. Any help is much appreciated. Thanks!

Related

sqlite3_bind_text not binding the value

Please find the code . I could not find any errors . but the "Type1" supplied to ? in SQL is not binded via SQLITE3_BIND_TEXT.
I need your help, since im an amatuer programmer in sqlite.
char * sql = "SELECT tube_id FROM tubes where type=?";
sqlite3_stmt * stmt;
sqlite3_prepare_v2 (db, sql, strlen (sql) + 1, & stmt, NULL);
int rc=sqlite3_bind_text(stmt,1, /* The number of the argument. */ "Type1",-1,SQLITE_STATIC/* The callback. */);
TRACE(_T("sql: %d %S\n "),rc, sql);
int s = sqlite3_step (stmt);
TRACE(_T("prepared query: %S\n"), sqlite3_sql(stmt));
if (s == SQLITE_DONE) {
int bytes;
const unsigned char * text;
bytes = sqlite3_column_bytes(stmt, 0);
text = sqlite3_column_text (stmt, 0);
TRACE(_T("text: %S\n"), text);
TRACE(_T("stmt: %S\n"), bytes);
} else {
fprintf (stderr, "Failed.\n");
}
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
What #ColonelThirtyTwo told is correct. I have used SQLITE_ROW to over come this problem.
Regards,
Selva

select() message queue failed as bad address(EFAULT) on AIX 6.1.0.0

On AIX 6.1.0.0, select() system call support for message queue, see http://www-01.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.basetrf2/select.htm?lang=en
But the below code return failed with errno 14(EFAULT) after select() called:
int msgid = msgget(MQ_KEY, IPC_CREAT|06666);
if (-1 == msgid) {
if (errno != EEXIST) {
ETRACE("msgget() failed: key[%d], errno[%d]", MQ_KEY, errno);
return -1;
}
msgid = msgget(MQ_KEY, 0);
if (-1 == msgid) {
ETRACE("msgget() failed: key[%d], errno[%d]", MQ_KEY, errno);
return -1;
}
}
DTRACE("msgget() success: msgid[%d]", msgid);
/* time out */
struct timeval to;
to.tv_sec = 10;
to.tv_usec = 0;
/* select list */
struct {
int msgids[1];
} rlist, wlist, elist;
rlist.msgids[0] = msgid;
wlist.msgids[0] = msgid;
elist.msgids[0] = msgid;
/* number of list */
int nlist = 1 << 16;
/* int ret = select(nlist, (struct fd_set*)&rlist, (struct fd_set*)&wlist, (struct fd_set*)&elist, &to); */
int ret = select(nlist, (struct fd_set*)&rlist, NULL, NULL, &to);
if (0 == ret) {
WTRACE("select() timeout: ret[%d]", ret);
}
else if (ret < 0) {
ETRACE("select() failed: ret[%d], errno[%d]", ret, errno);
}
else {
ITRACE("select() success");
}
return 0;
Message queue support in select() and poll() is an AIX extension that is no longer enabled by default when compiling on AIX 5.3 and later versions. To enable it, compile with -D_MSGQSUPPORT (or #define _MSGQSUPPORT 1 before the first #include).
It is not mentioned on the select() manual page but the option is mentioned on the poll() manual page, and the same flag enables message queue support for both functions.

How to use epoll instead of select in this code?

In UNIX Network Programming Volume 1:Figure 6-22 ,there is a piece of code as follows:
/* include fig01 */
#include "unp.h"
int main(int argc, char **argv)
{
int i, maxi, maxfd, listenfd, connfd, sockfd;
int nready, client[FD_SETSIZE];
ssize_t n;
fd_set rset, allset;
char buf[MAXLINE];
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
maxfd = listenfd; /* initialize */
maxi = -1; /* index into client[] array */
for (i = 0; i < FD_SETSIZE; i++)
client[i] = -1; /* -1 indicates available entry */
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
/* end fig01 */
/* include fig02 */
for ( ; ; ) {
rset = allset; /* structure assignment */
nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) { /* new client connection */
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
#ifdef NOTDEF
printf("new client: %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL),
ntohs(cliaddr.sin_port));
#endif
for (i = 0; i < FD_SETSIZE; i++)
if (client[i] < 0) {
client[i] = connfd; /* save descriptor */
break;
}
if (i == FD_SETSIZE)
err_quit("too many clients");
FD_SET(connfd, &allset); /* add new descriptor to set */
if (connfd > maxfd)
maxfd = connfd; /* for select */
if (i > maxi)
maxi = i; /* max index in client[] array */
if (--nready <= 0)
continue; /* no more readable descriptors */
}
for (i = 0; i <= maxi; i++) { /* check all clients for data */
if ( (sockfd = client[i]) < 0)
continue;
if (FD_ISSET(sockfd, &rset)) {
if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
/*4connection closed by client */
Close(sockfd);
FD_CLR(sockfd, &allset);
client[i] = -1;
} else
Writen(sockfd, buf, n);
if (--nready <= 0)
break; /* no more readable descriptors */
}
}
}
}
/* end fig02 */
I want to know how to use "epoll" instead "select" in here,But I have little knowledge about epoll,so can anyone give me some points ? Thanks.
You can go through this link. However, Before using epoll you need to be sure of the below points -
Do you want your system to be targeted as cross platform system (I mean which can be run under multiple operating system?) - Because epoll is available only in Linux system.
What is your targeted kernel version of Linux? Because epoll is only available in Linux 2.6. In case both these questions are answered and you feel epoll is not a restriction, you can go ahead with this.
HTH!

How do I loop mount programmatically?

I have recently written a guide on how to mount partitions from image files on Raspberry Pi.SE. The instructions are rather complicated and I have a bit of time, so want to replace them by a C program. I have successfully listed the partitions of the image and calculated to appropriate offsets.
In the original instructions, we needed to run
$ sudo mount -o loop,offset=80740352 debian6-19-04-2012.img /mnt
I now need to do this in code. I have found the mount function and libmount in util-linux.
I have now found loopdev.c in util-linux. Is there an easy way to create loop devices or do I have to learn from this code and use ioctl?
The following function binds the loop device device to file at offset. It returns 0 on success, 1 otherwise.
int loopdev_setup_device(const char * file, uint64_t offset, const char * device) {
int file_fd = open(file, O_RDWR);
int device_fd = -1;
struct loop_info64 info;
if(file_fd < 0) {
fprintf(stderr, "Failed to open backing file (%s).\n", file);
goto error;
}
if((device_fd = open(device, O_RDWR)) < 0) {
fprintf(stderr, "Failed to open device (%s).\n", device);
goto error;
}
if(ioctl(device_fd, LOOP_SET_FD, file_fd) < 0) {
fprintf(stderr, "Failed to set fd.\n");
goto error;
}
close(file_fd);
file_fd = -1;
memset(&info, 0, sizeof(struct loop_info64)); /* Is this necessary? */
info.lo_offset = offset;
/* info.lo_sizelimit = 0 => max avilable */
/* info.lo_encrypt_type = 0 => none */
if(ioctl(device_fd, LOOP_SET_STATUS64, &info)) {
fprintf(stderr, "Failed to set info.\n");
goto error;
}
close(device_fd);
device_fd = -1;
return 0;
error:
if(file_fd >= 0) {
close(file_fd);
}
if(device_fd >= 0) {
ioctl(device_fd, LOOP_CLR_FD, 0);
close(device_fd);
}
return 1;
}
References
linux/loop.h
piimg

MPI programming issue with MPI_Gather

I am trying to use MPI to sort digits, after sorting by the different processors I want to use MPI_Gather to collect and later print all the sorted numbers but this is not working. Any help will be appreciated. Below is my code.
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <mpi.h> /* Include MPI's header file */
/* The IncOrder function that is called by qsort is defined as follows */
int IncOrder(const void *e1, const void *e2)
{
return (*((int *)e1) - *((int *)e2));
}
void CompareSplit(int nlocal, int *elmnts, int *relmnts, int *wspace, int keepsmall);
//int IncOrder(const void *e1, const void *e2);
int main(int argc, char *argv[]){
int n; /* The total number of elements to be sorted */
int npes; /* The total number of processes */
int myrank; /* The rank of the calling process */
int nlocal; /* The local number of elements, and the array that stores them */
int *elmnts; /* The array that stores the local elements */
int *relmnts; /* The array that stores the received elements */
int oddrank; /* The rank of the process during odd-phase communication */
int evenrank; /* The rank of the process during even-phase communication */
int *wspace; /* Working space during the compare-split operation */
int i;
MPI_Status status;
/* Initialize MPI and get system information */
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &npes);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
n = 30000;//atoi(argv[1]);
nlocal = n/npes; /* Compute the number of elements to be stored locally. */
/* Allocate memory for the various arrays */
elmnts = (int *)malloc(nlocal*sizeof(int));
relmnts = (int *)malloc(nlocal*sizeof(int));
wspace = (int *)malloc(nlocal*sizeof(int));
/* Fill-in the elmnts array with random elements */
srand(time(NULL));
for (i=0; i<nlocal; i++) {
elmnts[i] = rand()%100+1;
printf("\n%d:",elmnts[i]); //print generated random numbers
}
/* Sort the local elements using the built-in quicksort routine */
qsort(elmnts, nlocal, sizeof(int), IncOrder);
/* Determine the rank of the processors that myrank needs to communicate during
* ics/ccc.gifthe */
/* odd and even phases of the algorithm */
if (myrank%2 == 0) {
oddrank = myrank-1;
evenrank = myrank+1;
} else {
oddrank = myrank+1;
evenrank = myrank-1;
}
/* Set the ranks of the processors at the end of the linear */
if (oddrank == -1 || oddrank == npes)
oddrank = MPI_PROC_NULL;
if (evenrank == -1 || evenrank == npes)
evenrank = MPI_PROC_NULL;
/* Get into the main loop of the odd-even sorting algorithm */
for (i=0; i<npes-1; i++) {
if (i%2 == 1) /* Odd phase */
MPI_Sendrecv(elmnts, nlocal, MPI_INT, oddrank, 1, relmnts,
nlocal, MPI_INT, oddrank, 1, MPI_COMM_WORLD, &status);
else /* Even phase */
MPI_Sendrecv(elmnts, nlocal, MPI_INT, evenrank, 1, relmnts,
nlocal, MPI_INT, evenrank, 1, MPI_COMM_WORLD, &status);
CompareSplit(nlocal, elmnts, relmnts, wspace, myrank < status.MPI_SOURCE);
}
MPI_Gather(elmnts,nlocal,MPI_INT,relmnts,nlocal,MPI_INT,0,MPI_COMM_WORLD);
/* The master host display the sorted array */
//int len = sizeof(elmnts)/sizeof(int);
if(myrank == 0) {
printf("\nSorted array :\n");
int j;
for (j=0;j<n;j++) {
printf("relmnts[%d] = %d\n",j,relmnts[j]);
}
printf("\n");
//printf("sorted in %f s\n\n",((double)clock() - start) / CLOCKS_PER_SEC);
}
free(elmnts); free(relmnts); free(wspace);
MPI_Finalize();
}
/* This is the CompareSplit function */
void CompareSplit(int nlocal, int *elmnts, int *relmnts, int *wspace, int keepsmall){
int i, j, k;
for (i=0; i<nlocal; i++)
wspace[i] = elmnts[i]; /* Copy the elmnts array into the wspace array */
if (keepsmall) { /* Keep the nlocal smaller elements */
for (i=j=k=0; k<nlocal; k++) {
if (j == nlocal || (i < nlocal && wspace[i] < relmnts[j]))
elmnts[k] = wspace[i++];
else
elmnts[k] = relmnts[j++];
}
} else { /* Keep the nlocal larger elements */
for (i=k=nlocal-1, j=nlocal-1; k>=0; k--) {
if (j == 0 || (i >= 0 && wspace[i] >= relmnts[j]))
elmnts[k] = wspace[i--];
else
elmnts[k] = relmnts[j--];
}
}
}
If I understand your code you've gathered the separately-sorted sublists back onto one process into the array relmnts ? And then printed them in order of occurrence. But I can't see where you've done anything about sorting relmnts. (I often don't understand other people's code, so if I have misunderstood stop reading now.)
You seem to be hoping that the gather will mysteriously merge the sorted sub-lists into a sorted list for you. It ain't going to happen ! You will need to merge the elements from the sorted sub-lists yourself, possibly after gathering them back to one process, or possibly doing some sort of 'cascading gather'.
By this I mean, suppose that you had 32 processes, and 32 sub-lists, then you would merge the sub-lists from process 1 and process 2 onto process 1, 3 and 4 onto 3, ..., 31 and 32 onto 31. Then you would merge from process 1 and 3 onto 1, .... After 5 steps you'd have the whole list merged, in sorted order, on process 1 (I'm a Fortran programmer, I start counting at 1, I should have written 'the process with rank 0' etc).
Incidentally, the example you put in your comment to your own question may be misleading: it sort of looks like you gathered 3 sub-lists each of 4 elements and rammed them together. But there are no elements in sub-list 1 which are smaller than any of the elements in sub-list 2, that sort of thing. How did that happen if the original list was unsorted ?

Resources