Precompile embedded sql in c on ubuntu linux db2 does not work - c

I asked before but it looks like its not me, its the system..
My db2 installation completed with "minor errors" so maybe that is it.
I can't make out the error code explanations.
The content of the folder:
prog1.sqc sh.sh
I gave DBADM authority to instance user.
It should create bnd file on its own, correct?
Here is the report:
$ db2 precompile prog1.sqc bindfile
LINE MESSAGES FOR prog1.sqc
------ --------------------------------------------------------------------
SQL0060W The "C" precompiler is in progress.
SQL0031C File "/home/nikica/UCENJE/precompile/prog1.bnd"
could not be opened.
SQL0095N No bind file was created because of previous
errors.
SQL0091W Precompilation or binding was ended with "2"
errors and "0" warnings.
IBM support pages:
https://www.ibm.com/support/pages/running-db2look-db2-instance-user-fails-sql0031c-file-db2lkfunbnd-could-not-be-opened
EDIT: my sqc
#include <stdio.h>
#include <string.h>
#include <sqlca.h>
/* SQL includes */
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL END DECLARE SECTION;
int main()
{
// EXEC SQL CONNECT TO sample;
return (0);
}

RESOLVED with
Precompilation or binding was ended with "0"
errors and "0" warnings.
Thanks to mao
Did all the steps like 100 times before plus "su - root" in the beginning

Related

Postgres ECPG: adding a function outside main() breaks the program

I have successfully connected and obtained data from Postgresql with my C application. My connector.pgc file looks like this:
#include <stdlib.h>
#include <stdio.h>
//#include "connect.h" // PROBLEM
int connect(); //NO PROBLEM
EXEC SQL BEGIN DECLARE SECTION;
char dbname[1024];
const char *target = "dbname#host:port";
const char *user = "user";
const char *passwd = "password";
EXEC SQL END DECLARE SECTION;
int main() {
EXEC SQL CONNECT TO :target AS con1 USER :user USING :passwd;
EXEC SQL SELECT pg_catalog.set_config('search_path', 'schema_name', false); EXEC SQL COMMIT;
EXEC SQL SET CONNECTION con1;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database is '%s'\n", dbname);
EXEC SQL DISCONNECT ALL;
// connect();
return 0;
}
// PROBLEM
//int connect(){
// printf("A\n");
// return 0;
//}
except, of course, username/password/schema_name/etc. are replaced with actual values.
I then do the following:
ecpg connector.pgc && gcc connector.c -o connectorXec -lecpg -L/usr/pgsql-12/lib && ./connectorXec
My operating system is a default CentOS 8.
ecpg --version returns ecpg (PostgreSQL) 13.2
psql --version returns psql (PostgreSQL) 12.8
The program compiles fine and I am able to connect without issues, the way I know this is printf extracts the correct database name, and I've also run other SQL SELECTS to confirm the data.
However, as soon as I uncomment the int connect() function, even without using it, it is called 3 times before the actual program, and I do not know why. To be more precise, I see the letter A being printed 3 times. Additionally, printf no longer displays the correct name, instead dbname is empty.
I tried putting int connect() function into a separate connect.c file, then linking it together with this program through connect.h, and the result is the same.
If I put the contents of main() into connect(), and then call it, the process just hangs indefinitely.
Truly, I am at a loss, and I do not have even the slightest idea of where to begin, since this situation seems impossible. I checked the connector.c file that ECPG produces and there are no additional calls. Most references I can find online contain only main() function, and in rare cases where they do not, there is no mention of any remotely similar issue.
Any ideas as to what's going on?
OK, so it turns out the connect() function is used somewhere, since renaming it solved the issue. I was renaming it in the created connector.c file, which is how I missed this obvious solution.
Laurenz Albe said that he tried this on his end and everything is fine, which means it is somehow unique to my setup.

C program exits giving error ORA-12162: TNS:net service name is incorrectly specified

I am working on a remote red-hat server and there I'm developing a c application to insert data in to a remote oracle database. So first i installed the OCI instant client rpm on the server and tried to compile a sample program. after certain linkages I could compile it. But then when I am going to run it. It exits giving an error saying
ORA-12162: TNS:net service name is incorrectly specified
The sample code I used is from the blog (refer to this code in case you need to clarify the things.where I’m quoting only few pieces to this post) René Nyffenegger's collection of things on the web
René Nyffenegger on Oracle
(refer to this code in case you need to clarify the things.where I’m quoting only few pieces to this post)
In the code I added some prints to check for the error And it seems like It gets stuck in the OCIServerAttach() function r gives a printed walue of -1
r=OCIServerAttach(srv, err, dbname, strlen(dbname), (ub4) OCI_DEFAULT);
printf("r value %d",r);
if (r != OCI_SUCCESS) {
checkerr(err, r);
goto clean_up;
}
Another point is that in the compilation process it gives a warning saying that a certain libry is not include. but the exicutable file is created. Here is the massage I get in the compilation process.
[laksithe#loancust ~]$ gcc -L$ORACLE_HOME/lib/ -L$ORACLE_HOME/rdbms/lib/ -o oci_test oci_test.o -L/usr/lib/oracle/12.1/client64/lib -lclntsh `cat $ORACLE_HOME/lib/sysliblist`
cat: /lib/sysliblist: No such file or directory
Going through the web I found that by creating a tnsnames.ora file with the connection details I could solve the problem. But even It didn't work for me. Here is the link for that blog blog
It has been a week since this error and I cold'nt solve it. could someone please help me.
connection string format I used is abc.ghi.com:1521/JKLMN
My recommendation is to bypass tnsnames completely. Oracle has always allowed you to put in the direct connection details, but EZConnect makes that even easier.
When you format your connection string, instead of listing the TNS name, use the actual connection properties in the following format:
servername:port/service name
For Example
MyOracle.MyCompany.Com:1521/SalesReporting
Your connection string might also require direct=true, but I'm honestly not sure.
I like the idea of tnsnames, but it's a double edged sword. When it works, it's great. When it doesn't, you want to throw something. With EZConnect, it always works.
By the way, if you don't know the properties of the three items above, find a machine that connect via tnsnames and:
tnsping <your TNS-named database>

Raspberry PI 2 - How to get file-access for c-program to write on disc

i am using Raspbian on a RPI2 and i tried to create/change a SQLite database from a C-Program.
here a little bit code:
static sqlite3 *db;
static char *zErrMsg = 0;
//....
sqlite3_open(PATH_DATABASE, &db);
char *sql_statement = "CREATE TABLE IF NOT EXISTS myTable (datetime BIGINT, myVal BIGINT)";
sqlite3_exec(db,sql_statement, NULL, NULL, &zErrMsg);
sqlite3_close(db);
As IDE i use Eclipse CDT.
In Eclipse Debug-Mode and with executing the program by double click (in "sudo startx" mode), raspbian creates me a database file.
If i start my program via terminal (sudo /home/pi/test/myProgram)
no database-file could be created.
Folder "test" and executable "myProgram" have both chmod 755 access.
I searched a lot, found nothing that helps me.
Each one of the sqlite3 functions returns an error code. After every call, check that the error code is SQLITE_OK. If it isn't, then the function failed, and you need to handle the error.
You can call sqlite3_errstr to convert the error code to a string.
For more information about error handling in sqlite3, see https://www.sqlite.org/c3ref/errcode.html .

C script running as cron giving permission denied error

I have a .c file compiled and would like to run via a cron job but I end up getting this error:
/bin/sh: /usr/local/bin/get1Receive.c: Permission denied.
What is causing this error and how do I fix it?
Should I be running the .c file in cron or a different compiled file?
Results from /tmp/myvars
GROUPS=()
HOME=/root
HOSTNAME=capture
HOSTTYPE=x86_64
IFS='
'
LOGNAME=root
MACHTYPE=x86_64-redhat-linux-gnu
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PATH=/usr/bin:/bin
POSIXLY_CORRECT=y
PPID=11086
PS4='+ '
PWD=/root
SHELL=/bin/sh
SHELLOPTS=braceexpand:hashall:interactive-comments:posix
SHLVL=1
TERM=dumb
UID=0
USER=root
_=/bin/sh
Results from file get1Receive.c
file get1Receive.c
get1Receive.c: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
Snippet of codes.
sprintf(queryBuf1,"SELECT ipDest, macDest,portDest, sum(totalBits) FROM dataReceive WHERE timeStampID between '%s' And '%s' GROUP BY ipDest, macDest, portDest ",buff1,buff2);
printf("\nQuery receive %s",queryBuf1);
if(mysql_query(localConn, queryBuf1))
{
//fprintf(stderr, "%s\n", mysql_error(localConn));
printf("Error in first query of select %s\n",mysql_error(localConn));
exit(1);
}
localRes1 = mysql_store_result(localConn);
int num_fields = mysql_num_fields(localRes1);
printf("\nNumf of fields : %d",num_fields);
printf("\nNof of row : %lu",mysql_num_rows(localRes1));
If the output of this command:
file get1Receive1.c
shows that file name to be a valid executable that part is very unusual, but okay.
Assuming you are using biz14 (or your real username's ) crontab try this:
use the command crontab -e to create this line in your crontab:
* * * * * set > /tmp/myvars
Wait a few minutes, go back into crontab -e and delete that entry.
Use the set command from the command line to see what variables and aliases exist.
Compare that with that you see in /tmp/myvars You have to change how your C code executes by changing the variables and aliases the cron job runs with.
If you are running the cron job in someone else's crontab, then you have a bigger problem. Check file permissions on get1Receive1.c. and the directory it lives in. That other user (the one who wons the crontab) has to have permissions set on your directory and get1Receive1.c so the job can run.
Example crontab entry:
0 10 * * 1-5 /path/to/get1Receive1.c > /tmp/outputfile
Read /tmp/outputfile to see what you got. You are using printf in your code. printf only writes to the controlling terminal. There is no controlling terminal, so redirect the printf stuff to a file.
Last effort on this problem:
Check return codes on EVERYTHING. All C functions like fread(), any db function, etc. If a return code gives a fail response ( these are different for different function calls) then report the error number the line number and function - gcc provides LINE and func. Example:
printf("error on line %d in my code %s, error message =%s\n", __LINE__, __func__, [string of error message]);
If you do not check return codes you are writing very poor C code.
CHECK return codes, please, now!
Permission wise you could have two issues.
1. The 'c' file's permissions don't allow who you are running it as to run it.
2. You are running the cron with a script which doesn't have permissions.
Here's a helpful post: How to give permission for the cron job file?
The fact that you are running a 'c' file and referring to it as a script makes me think you're using C shell and not writing it as a C language program which would need to be compiled and have the generated executable run by the cron. If you're not using gcc or have never called gcc on your 'C' script then it's not C and call it C shell to avoid confusion.

The same error is detected in stored **procedure**, but not in stored **function**

This question is related to my previous one: RaiseError (PERL, DBI) equivalent for unixODBC C API?
As I isolated the problem later, I'll post new question, that is more specific, isolated and without unnecessary information.
Version: unixODBC 2.3.0
lib: unixODBC - C API
Suppose I have a stored FUNCTION:
CREATE FUNCTION "test".func() RETURNING LVARCHAR(1000);
set debug file to '/home/directory_does_not_exists/unknown.log';
trace off;
trace on;
trace off;
return 'result is set here';
END FUNCTION;
And the same body, but in stored PROCEDURE:
CREATE PROCEDURE "test".proc(pDummy SMALLINT)
set debug file to '/home/directory_does_not_exists/unknown.log';
trace off;
trace on;
LET pDummy = 2;
trace off;
END PROCEDURE;
As you can see, they are absolutely the same. The path to debug file is wrong, so error is expected. When I execute call func() from Aqua Data Studio the error is detected:
Cannot open DEBUG file for SPL routine trace
It's the same for call proc(1).
BUT when I execute these 2 calls through unixODBC (using SQLExecute),
execute procedure proc(1);
returns SQL_ERROR (which is expected and fine), while
execute function func();
returns SQL_SUCCESS.. BUT 'result is set here' is not returned, empty string ('') is returned, instead..
Executing call func() gives the same results, as execute function func();
Calling SQLMoreResults returns SQL_NO_DATA, SQLFetch returns SQL_ERROR.
Any ideas?
I don't use Informix but the simple examples I've tried with Perl DBD::ODBC and also from isql (written in C) all return an error:
use strict;
use warnings;
use DBI;
my $h = DBI->connect();
eval {
$h->do(q/drop function fmje/);
};
$h->do(<<'EOS');
create function fmje (#p1 as int)
returns int
as
begin
declare #a int;
set #a = 'fred';
return #p1;
end;
EOS
my $s = $h->prepare(q/{? = call fmje(?)/);
$s->bind_param_inout(1, \my $x, 10);
$s->bind_param(2, 1);
$s->execute;
print "return is ", ($x ? $x : "undef"), "\n";
isql -v baugi sa easysoft
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> {call fmje(1)}
[22005][unixODBC][Easysoft][SQL Server Driver 11.0][SQL Server]Conversion failed when converting the varchar value 'fred' to data type int.
[ISQL]ERROR: Could not SQLExecute
SQL>
Informix must work differently for functions or perhaps you are not using generic ODBC via Aqua Data Studio.
If you see the error from Perl as you say in your other post then do as I recommended there and add:
[ODBC]
Trace=yes
TraceFile=/tmp/unixodbc.log
to the top of your odbcinst.ini file and run the Perl. Then show us the lines from the log from the error. Then repeat with isql so we can compare the ODBC calls.
This may be something to do with the server version you are using (unlikely, but possible), or to do with the API you are using. When I test with IDS 11.70.FC2 on MacOS X 10.7 using (my) sqlcmd program build with ESQL/C (CSDK) 3.70.FC2, I get:
$ sqlcmd -c -d stores -e begin -xf x1.sql -e 'execute procedure proc(2)' \
-e 'execute function func()'
+ CREATE FUNCTION "test".func() RETURNING LVARCHAR(1000);
set debug file to '/home/directory_does_not_exists/unknown.log';
trace off;
trace on;
trace off;
return 'result is set here';
END FUNCTION;
+ CREATE PROCEDURE "test".proc(pDummy SMALLINT)
set debug file to '/home/directory_does_not_exists/unknown.log';
trace off;
trace on;
LET pDummy = 2;
trace off;
END PROCEDURE;
+ execute procedure proc(2)
SQL -648: Cannot open DEBUG file for SPL routine trace.
SQLSTATE: IX000 at /dev/stdin:0
+ execute function func()
SQL -648: Cannot open DEBUG file for SPL routine trace.
at /dev/stdin:0
$
As you can see, both func() and proc() correctly report an error in ESQL/C. So, the problem is almost certainly in the client-side code - in the ODBC driver and the way it is handling the errors, or in the code calling the ODBC driver.
How to isolate the problem more?
Run your test with SQLIDEBUG=2:xyz in the environment. Then, find the file with a names starting xyz_ (I got xyz_35424_0_819800, for example) and run sqliprint on it. That will show you whether the server is generating the error message twice.
I got two packets similar to this in the one trace:
S->C (12) Time: 2011-07-28 00:28:02.41736
SQ_ERR
SQL error..........: -648
ISAM/RSAM error....: 0
Offset in statement: 0
Error message......: "" [0]
SQ_EOT
If you see the two packets with the -648 error, then you know the problem is in the way the client is handling the error. If you don't see the two errors, then I'm very curious to see what is going on.
First of all - thanks a lot to #Jonathan Leffler(for the hint with SQLIDEBUG=2:xyz + sqliprint and testing on his machine) and #bohica (for the hint with strace ) for the support! That really helped me to find the real problem and solve it! +1 from me for both.
Unfortunately, the answer was not in their posts, that's why I'll answer it my own.
Summary:
SQLPrepare and SQLExecute fail sometimes on some errors, but not all. When stored procedure is used, these functions catch more errors. Unfortunately, the situation is different with stored functions.
How I catch the errors now? If SQLExecute is successfull, I call SQLNumResultCols - that's normal. After that, I call SQLFetch which is also expected. BUT, as SQLFetch may fail for many reasons (for example, it always fails on stored procedures), it's error is ignored. And there's a while like
if ( SQLNumResultCols( stmt, &nAllCols ) != SQL_SUCCESS )
// ...
int nSucceededFetches = 0; // added now, see below why
while ( SQL_SUCCEEDED( SQLFetch( stmt ) ) )
{
++nSucceededFetches; // added now, see below why
/* bla bla */
}
And here's the key - add additional check:
if( 0 == nSucceededFetches && nColumns > 0 )
which says - if there are returned columns and fetch fails on the FIRST call, then something's wrong. Then I have
while ( SQL_SUCCESS == SQLError( 0, 0, stmt, szSqlState, &nNativeError, szError, 500, &nErrorMsg ) )
{ /* bla bla */ }
And everything's fine. I still don't understand why SQLExecute returns SQL_SUCCESS (NOT even SQL_SUCCESS_WITH_INFO ..), but it doesn't matter.

Resources