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;
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;
}
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 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;
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;
First of all (in case this is important) I'm using ActiveState's Perl (v5.8.7 built for MSWin32-x86-multi-thread).
I've just emerged from a three hour long debugging session, trying to find the source of an error. I found there was simply no error, but for some reason ADO's connection object was getting the Errors.Count increased with each printed message in my stored procedure's output.
Consider following Transact SQL code:
CREATE PROCEDURE dbo.My_Sample() AS
BEGIN TRAN my_tran
-- Does something useful
if ##error <> 0 BEGIN
ROLLBACK TRAN my_tran
RAISERROR( 'SP My_Sample failed', 16, 1)
END ELSE BEGIN
COMMIT TRAN my_tran
PRINT 'SP My_Sample succeeded'
END
Now imagine a Perl sub more or less like:
sub execute_SQL {
# $conn is an already opened ADO connection object
# pointing to my SQL Server
# $sql is the T-SQL statement to be executed
my($conn, $sql) = #_;
$conn->Execute($sql);
my $error_collection = $conn->Errors();
my $ecount = $error_collection->Count;
if ($ecount == 0 ) { return 0; }
print "\n" . $ecount . " errors found\n";
print "Executed SQL Code:\n$sql\n\n";
print "Errors while executing:\n";
foreach my $error (in $error_collection){
print "Error: [" . $error->{Number} . "] " . $error->{Description} . "\n";
}
return 1;
}
Somewhere else, in the main Perl code, I'm calling the above sub as:
execute_SQL( $conn, 'EXEC dbo.My_Sample' );
In the end I got it that every PRINT statement causes a new pseudo-error to be appended to the ADO Errors collection. The quick fix I implemented was to change that PRINT in the SP into a SELECT, to bypass this.
The questions I'd like to ask are:
Is this behaviour normal?
Is there a way to avoid/bypass it?
This is to be expected as it's what ADO does and the Win32::ADO is quite a thin layer above it.
ref: knowledge base note that the RAISERROR and PRINT statements are returned through the ADO errors collection
OK, after a lot of testing and reading, I came to found it explained in the BOLs' article "Using PRINT" (my emphasis):
The PRINT statement is used to return messages to applications. PRINT takes either a character or Unicode string expression as a parameter and returns the string as a message to the application. The message is returned as an informational error to applications using the SQLClient namespace or the ActiveX Data Objects (ADO), OLE DB, and Open Database Connectivity (ODBC) application programming interfaces (APIs). SQLSTATE is set to 01000, the native error is set to 0, and the error message string is set to the character string specified in the PRINT statement. The string is returned to the message handler callback function in DB-Library applications.
Armed with this knowledge I adapted this VB6 from this DevX article until I got this:
sub execute_SQL {
# $conn is an already opened ADO connection object
# pointing to my SQL Server
# $sql is the T-SQL statement to be executed
# Returns 0 if no error found, 1 otherwise
my($conn, $sql) = #_;
$conn->Execute($sql);
my $error_collection = $conn->Errors();
my $ecount = $error_collection->Count;
if ($ecount == 0 ) { return 0; }
my ($is_message, $real_error_found);
foreach my $error (in $error_collection){
$is_message = ($error->{SQLState} eq "01000" && $error->{NativeError}==0);
$real_error_found=1 unless $is_message;
if( $is_message) {
print "Message # " . $error->{Number}
. "\n Text: " . $error->{Description} ."\n";
} else {
print "Error # " . $error->{Number}
. "\n Description: " . $error->{Description}
. "\nSource: " . $error->{Source} . "\n";
}
}
print $message_to_print;
return $real_error_found;
}
So now my Perl sub correctly sorts out real errors (emitted from SQL Server via a RaisError) and a common message outputted via "PRINT".
Thanks to Richard Harrison for his answer which lead me to the way of success.