I am trying to build a C program to generate partly random strings and insert a large number of them to db2 rows in a loop so I need it to insert from embedded SQL.... The program does everything except inserts.
I can make a select query, c compiler, db2 precompiler and binder all execute with no errors.
It does not even let me make an insert with hard coded variables let alone with host variables and the query is perfectly successful from terminal line
db2 "INSERT INTO
SYT006_COUNTRY(SL_ISO2,BZ_COUNTRY,KZ_RISK)
VALUES
('XY', 'wont work from embedded SQL', 'R')"
Host variables defined as char arrays with one more position for terminator. Platform is Ubuntu.
I tried a million things so here is the code.. EDIT everything obsolete cleared
#include <stdio.h>
#include <string.h>
#include <sqlca.h>
#include <stdlib.h>
#include <sqlenv.h>
#include <sqlcodes.h>
#include <sqlutil.h>
#include <time.h>
#include "utilemb.h"
#include "sqlaprep.h"
/* SQL includes */
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL DECLARE SYT006_COUNTRY TABLE
(
KEYFIELD INT,
SL_ISO2 CHAR(2) NOT NULL,
BZ_COUNTRY CHAR(30) NOT NULL,
KZ_RISK CHAR(1) NOT NULL
) ;
char hostVar[31];
EXEC SQL END DECLARE SECTION;
int main()
{
/* connect to the database REQUIRED */
printf("Connecting to database...\n ");
EXEC SQL CONNECT TO "sample";
if (SQLCODE <0)
{
printf("Connect Error. Code: %d\n", sqlca.sqlcode);
}
else
{
printf("Connected to database. Code: %d\n",sqlca.sqlcode );
}
/* works only from command line terminal*/
EXEC SQL
INSERT INTO
SYT006_COUNTRY(SL_ISO2,BZ_COUNTRY,KZ_RISK)
VALUES
('XY', 'please', 'R');
/* this one works perfectly normal*/
/*
EXEC SQL SELECT BZ_COUNTRY INTO :hostVar
FROM SYT006_COUNTRY WHERE KEYFIELD = 515;
printf("printing hostVar: %s\n", hostVar);
*/
printf("MAIN FINISH \n");
return (0);
}/*end main*/
the only out of order thing I get is when i start db2 from my shell script:
SQL5043N Support for one or more communications protocols specified in the DB2COMM environment variable failed to start successfully. However, core database manager functionality started successfully.
SQL1063N DB2START processing was successful.
Nothing better then a cup of coffee the next day.
Embedded-SQL program requires the line
EXEC SQL COMMIT;
Related
I am unable to connect to my db instace orclpdb1 from PRO*c code. I tried to debug and it's showing some other db name which that doesn't exist.
void Svc_Login() {
varchar orauid[ USER_ID_SIZE ];
varchar oraupw[ PASSWORD_SIZE ];
int table_count=0;
char curr_schema[20];
char curr_db[20];
char str_user_id[20];
char str_user_pw[20];
/*TDT,II - 02 May 2006 - Added Level 1 Debugging */
if ( iDebug >= 1 ) WriteTrace( "Running Svc_Login" );
orauid.len = sprintf( orauid.arr, "item" );
oraupw.len = sprintf( oraupw.arr, "item" );
EXEC SQL CONNECT :orauid IDENTIFIED BY :oraupw;
EXEC SQL select user into :curr_schema from dual;
sprintf( cLogText, "Connecting with username %s and password %s",VARCHAR2CHAR(str_user_id, orauid),VARCHAR2CHAR(str_user_pw,oraupw);
WriteTrace(cLogText);
EXEC SQL select ora_database_name into :curr_db from dual;
sprintf( cLogText, "The current db is %s", curr_db );
WriteTrace(cLogText);
EXEC SQL select count(*) into :table_count from tab;
sprintf( cLogText, "The No.of Tables in %s schema is ~%d~", curr_schema,table_count );
WriteTrace(cLogText);
return; /* return to mainline code */
}
#define VARCHAR2CHAR(a,b) (strncpy(a, (char*)b.arr, b.len), a[b.len] = '\0')
the below is the environment specification script.
#!/bin/ksh
# Set Oracle environment up first
# Set Path and Oracle environment
VERSION=`uname -v`
RELEASE=`uname -r`
export ORACLE_HOME=/opt/oracle/product/19c/dbhome_1
export ORACLE_SID=orclpdb1
export PATH=$PATH:$ORACLE_HOME/bin
export WAUUSER=item
export WAUPASSW=item
export ITEMUSER=item
export ITEMPASSW=item
The below are the logs ffor debug statements indicating it's taking null values for user id and password. and sid name is is also different (32c). sid should be orclpdb1.
oracle#azureRHEL MenuPrograms]$ cd /opt/cao/logs/
[oracle#azureRHEL logs]$ cat caoforms.trc.log
04:40:19: Setting Debug Level to ~2~
04:40:19: Running Svc_Login
04:40:21: Connecting with username (null) and password (null)
04:40:21: The current db is 32c
04:40:21: The No.of Tables in k schema is ~0~
04:40:29: Running SecurityEnterKey
04:40:29: orLoginInfo.user_id_count value is ~0~
04:40:29: MAHESH
04:40:29:
04:40:31: Running wrap_up
[oracle#azureRHEL logs]$
EXEC SQL CONNECT :user IDENTIFIED BY :passw USING :dbstr; syntax worked. earlier USING was not added. now it's working fine. connection string should be given in :/SID format with help of host variable
#include <stdio.h>
EXEC SQL INCLUDE SQLCA.H;
EXEC SQL INCLUDE ORACA.H;
void check_err() {
if (sqlca.sqlcode < 0) {
printf("Error: %s\n", sqlca.sqlerrm.sqlerrmc);
exit(1);
}
}
int main() {
// Connect to the database
char uid[10]="item";
char upw[10]="item";
char dbsid[10]="orclpdb1";
char connect_string[50]="4.246.55.119:1521/orclpdb1";
EXEC SQL CONNECT :uid IDENTIFIED BY :upw USING :connect_string;
check_err();
// Get the number of tables
int num_tables;
EXEC SQL SELECT count(*) INTO :num_tables FROM tab;
check_err();
// Print the result
printf("Number of tables: %d\n", num_tables);
// Disconnect from the database
check_err();
return 0;
}
I am using FreeTDS to process simple SELECT statements.
My problem is that I cannot get more than the first 4096 bytes of a large column value.
Let's say we have a table like this:
CREATE TABLE tab (
largecol varbinary(max),
othercol int PRIMARY KEY
);
My code looks like this (simplified and omitting error checks):
#include <sybfront.h>
#include <sybdb.h>
int main ()
{
DBPROCESS *dbproc;
LOGINREC *login;
char *data;
DBINT len;
/* setup */
dbinit();
login = dblogin();
DBSETLUSER(login, "username");
DBSETLPWD(login, "password");
DBSETLAPP(login, "my_program");
DBSETLPACKET(login, 10000);
DBSETLNATLANG(login, "us_english");
DBSETLCHARSET(login, "UTF-8");
/* connect */
dbproc = dbopen(login, "hostname");
dbuse(dbproc, "dbname");
/* execute query */
dbcmd(dbproc, "SELECT largecol, othercol FROM tab");
dbsqlexec(dbproc);
dbresults(dbproc);
/* retrieve result */
dbnextrow(dbproc);
data = (char *)dbdata(dbproc, 1);
len = dbdatlen(dbproc, 1);
/* more processing */
}
Now no matter how large the data in largecol are, I never get more than 4096 bytes in data and len.
The only lead I have to make this work is the dbreadtext function, but I don't understand how to use it. The only bit of information I get is:
Use dbreadtext instead of dbnextrow to read SQLTEXT and SQLIMAGE values.
That function does not take a column number as argument, so I have no idea how to use it. Can it only be used with queries that retrieve only a single column?
How can I retrieve large column data?
FreeTDS has an option, text size, which can be set in freetds.conf:
See table 3.3, text size:
https://www.freetds.org/userguide/freetdsconf.html
Give that a try?
We are porting Oracle Pro*C code to PostgreSQL ECPG. We had several Oracle stored procedures that were ported into PostgreSQL functions like:
db1.update_some_logic(double precision, double precision, text, text)
On the C file I've tried several things but nothing seems to work.
Option 1:
EXEC SQL SELECT db1.update_some_logic(10411, 920, 'TYT','N');
Error 1:
too few arguments on line 4379
Option 2:
EXEC SQL BEGIN DECLARE SECTION;
const char *stmt2 = "SELECT db1.update_some_logic(10411, 920, 'TYT','N');";
EXEC SQL END DECLARE SECTION;
EXEC SQL EXECUTE IMMEDIATE :stmt2;
Error 2:
too few arguments on line 4384
The function clearly has 4 arguments, not sure what I am missing here.
I can reproduce the issue with PostgreSQL 12.3.
I have found following workaround:
the function should not return void but a value for example an integer
the ECPG program must execute the function and get the returned value with SELECT ... INTO:
EXEC SQL SELECT update_some_logic(10411, 920, 'TYT','N') INTO :v_key;
You'll need work with share variables for those parameters.
EXEC SQL BEGIN DECLARE SECTION;
double parameter_1;
double parameter_2;
char parameter_3[100];
char parameter_4[100];
int result; //I guess your function return int??
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT update_some_logic(:parameter_1, :parameter_2, :parameter_3, :parameter_4) INTO :result;
if (sqlca.sqlcode!=0)
{
printf("Error: %ld\n", sqlca.sqlcode);
printf("Message:%s\n", sqlca.sqlerrm.sqlerrmc);
}
printf("It works %d\n", result);
I am using using postgresql server on my laptop, and trying to connect with the database through my C program, using epcg. I wrote the following commands to precompile, compile and run the my .pgc program.
PRE-COMPIILE - epcg sql.pgc
COMPILE - gcc -c sql.c -I/usr/include/postgresql
RUN - gcc -o sql sql.o -L/usr/lib -lecpg
My program is getting compiled and run successfully, i.e., it is showing no errors.
But, when I try to retrieve my database at the command line prompt, using command,
COMMAND - psql database
No updates are there in the tables,i.e., the commands which I have written in the program, are not getting updated in the database.
The following is the code in .pgc file :
#include<stdio.h>
int main()
{
EXEC SQL CONNECT TO database;
EXEC SQL create table player(player_id int,player_name varchar(255),team varchar(10));
EXEC SQL create table player1(player_id int,player_name varchar(255),team varchar(10));
EXEC SQL INSERT INTO player VALUES(1,'ram','a');
EXEC SQL COMMIT;
EXEC SQL DISCONNECT database;
return 0;
}
The following is the code in C, after precompilation :
/* Processed by ecpg (4.7.0) */
/* These include files are added by the preprocessor */
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
/* End of automatic include section */
#line 1 "sql.pgc"
#include<stdio.h>
int main()
{
{ ECPGconnect(__LINE__, 0, "vidisha#localhost:5432" , NULL, NULL , NULL, 0); }
#line 8 "sql.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table player ( player_id int , player_name varchar ( 255 ) , team varchar ( 10 ) )", ECPGt_EOIT, ECPGt_EORT);}
#line 10 "sql.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table player1 ( player_id int , player_name varchar ( 255 ) , team varchar ( 10 ) )", ECPGt_EOIT, ECPGt_EORT);}
#line 11 "sql.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into player values ( 1 , 'ram' , 'a' )", ECPGt_EOIT, ECPGt_EORT);}
#line 12 "sql.pgc"
{ ECPGtrans(__LINE__, NULL, "commit");}
#line 14 "sql.pgc"
{ ECPGdisconnect(__LINE__, "vidisha");}
#line 16 "sql.pgc"
return 0;
}
Using the script you wrote I didn't get any changes in my test DB too.
So, using #vector advice, if I gave the username of my test DB, everything works:
Using this makefile:
default:
ecpg sql.pgc
gcc -c sql.c -I/usr/include/postgresql
gcc -o sql sql.o -L/usr/lib -lecpg
And, as an example, I'll use:
testdb as the database name
9876 as the port
testuser as the username
testpass as the password
with this sql.pgc:
#include <stdio.h>
int main() {
EXEC SQL CONNECT TO testdb#localhost:9876 USER 'testuser' IDENTIFIED BY 'testpass';
EXEC SQL create table player(player_id int,player_name varchar(255),team varchar(10));
EXEC SQL create table player1(player_id int,player_name varchar(255),team varchar(10));
EXEC SQL INSERT INTO player VALUES(1,'ram','a');
EXEC SQL COMMIT;
EXEC SQL DISCONNECT;
return 0;
}
everything worked well.
You also have to provide the password and the default port is 5432.
This code works fine for me.
testdb- databaseName, postgres - username, 123321 - password
_Also after once executing this program you have to remove both the create table lines else your code will not work (as the tables are alredy created). You will get no error as you have not done error handling. To learn about error handling and more click here. _
#include<stdio.h>
int main()
{
EXEC SQL CONNECT TO testdb#localhost:5432 USER 'postgres' USING '123321';
EXEC SQL create table player(player_id int,player_name varchar(255),team varchar(10));
EXEC SQL create table player1(player_id int,player_name varchar(255),team varchar(10));
EXEC SQL INSERT INTO player VALUES(1,'ram','a');
EXEC SQL COMMIT;
EXEC SQL DISCONNECT database;
return 0;
}
You have to set search path to your current database.
EXEC SQL SET SEARCH_PATH TO "your database";
Also, at the end, don't forget to commit.
EXEC SQL COMMIT;
I have the below code in my .pc file which is called by almost 10 processes but for one process its not working as showing "Core dump/Segmentation Fault" .
This is the code which is called by every process as the first step to connect to Database.
Please suggest where is the problem in the below code -:
void DatabaseLogon (void)
{
EXEC SQL BEGIN DECLARE SECTION;
char *pchORALOG="";
EXEC SQL END DECLARE SECTION;
EXEC SQL WHENEVER SQLERROR DO SQLError();
/* Save text of current SQL statement in the ORACA if an error occurs. */
oraca.orastxtf = ORASTFERR;
/* try to get the oracle login user/pass at the process level */
if ( (pchORALOG=getenv("oralog")) == NULL )
{
printf("Error:Cannot Logon to database!\n");
SQLError();
}
else
{
EXEC SQL CONNECT :pchORALOG;
}
} /* End Of DatabaseLogon */
Thanks
Arpita
My ProC connect statement looks like this:
EXEC SQL CONNECT :user IDENTIFIED BY :passwd USING :database;
you are trying to modify a read only location here.
pchORALOG=getenv("oralog")
below statement is the problem:
char *pchORALOG="";
change it to:
char *pchORALOG;