SQL Error ORA-01002 not autocommit and loop - c++

I'm using pro c/c++ in a unix environment. Inside a c function I create a simple select statement which is not inside a loop and autocommit is disabled.
This is the dynamic sql;
char sql_statement[200];
int num1, num2;
...
snprintf(sql_statement, sizeof(sql_sattement), "select column1, column2 from '%s' where num = '%d' and code_cfg = '%d'", "customer", 0, 0);
exec sql prepare instruction_to_execute from :sql_statement;
exec sql declare crs cursor for instruction_to_execute;
exec sql open crs;
exec sql fetch crs into :num1, :num2;
...
Executing this code gives me ORA-01002 error. As I said before, this code is not inside a loop and autocommit is off.
But if I write this code statically, works fine. Below the code:
EXEC SQL
SELECT column1, column2
INTO :num1, :num2
FROM CUSTOMER
where num = 0
AND code_cfg = 0;
SQL instruction is simple. For my understanding this code should be executed fine.
In SO I found some answers:
ORA-01002: fetch out of sequence C++
ORA-01002: fetch out of sequence
Hibernate error “ORA-01002” when persisting entity with custom Sequence Generator
ORA-01002: fetch out of sequence
java.sql.SQLException: ORA-01002: fetch out of sequence

Related

Query breaks whenever I add MAX() functions or grouping statements

I have some tables laid out like so:
Airplane
(airplaneID number(2) primary key, airplaneName char(20), cruisingRange number(5));
Flights
(airplaneID number (2), flightNo number(4) primary key,
fromAirport char(20), toAirport char(20), distance number(4), depart timestamp,
arrives timestamp, foreign key (airplaneID) references Airplane);
Employees
(employeeID number(10) primary key, employeeName char(18), salary number(7));
Certified
(employeeID number(10), airplaneID number(2),
foreign key (airplaneID) references Airplane,
foreign key (employeeID) references Employees );
And I need to write a query to get the following information:
For each pilot who is certified for at least 4 airplanes, find the
employeeName and the maximum cruisingRange of the airplanes for which
that pilot is certified.
The query I have written is this:
SELECT Employees.employeeName, MAX(Airplane.cruisingRange)
FROM Employees
JOIN Certified ON Employees.employeeID = Certified.employeeID
JOIN Airplane ON Airplane.airplaneID = Certified.airplaneID
GROUP BY Employees.employeeName
HAVING COUNT(*) > 3
Lastly, this is the function that executes and reads in the query information:
void prepareAndExecuteIt() {
// Prepare the query
//sqlQueryToRun.len = strlen((char *) sqlQueryToRun.arr);
exec sql PREPARE dbVariableToHoldQuery FROM :sqlQueryToRun;
/* The declare statement, below, associates a cursor with a
* PREPAREd statement.
* The cursor name, like the statement
* name, does not appear in the Declare Section.
* A single cursor name can not be declared more than once.
*/
exec sql DECLARE cursorToHoldResultTuples cursor FOR dbVariableToHoldQuery;
exec sql OPEN cursorToHoldResultTuples;
int i = 0;
exec sql WHENEVER NOT FOUND DO break;
while(1){
exec sql FETCH cursorToHoldResultTuples INTO empName, cruiseRange;
printf("%s\t", empName);
printf("%s\n", cruiseRange);
i++;
// This is temporary while I debug so it doesn't just loop on forever when the query breaks.
if (i > 500){
printf("Entered break statement\n");
break;
}
}
exec sql CLOSE cursorToHoldResultTuples;
}
The query works until I add the MAX(), GROUP BY, and HAVING statements. Then it just reads in nothing infinitely. I don't know if this is an issue with the way I've written my query or if it's an issue with the C++ code that executes it. I'm using the ProC interface to access an Oracle database. Any ideas as to what's going wrong?
You can't mix implicit and explicit joins. I suggest
SELECT Employees.employeeName, MAX(Airplane.cruisingRange)
FROM Employees
JOIN Certified ON Employees.employeeID = Certified.employeeID
JOIN Airplane ON Airplane.airplaneID = Certified.airplaneID
GROUP BY Employees.employeeName
HAVING COUNT(*) > 3
which works fine.
db<>fiddle here

Teiid execute immediate gives a parsing error when executing long queries

I'm using virtual procedures to expose a REST API using teiid. In my virtual procedure i am using execute immediate to execute SQL queries which takes input parameters from the virtual procedure as filters to the where clause (dynamic where cluase). This works fine for small select queries but when the query length is above a particular length it gives an parsing error.
Is there any solution for this problem?
Is there any alternative way of implementing dynamic where clauses in my SQL query?
Lets assume that the fallowing query has around 4000 characters. this works fine.
CREATE VIRTUAL PROCEDURE GetVals(IN filters string) RETURNS (json clob) OPTIONS (UPDATECOUNT 0, "REST:METHOD" 'GET', "REST:URI" 'get_vals')
AS
BEGIN execute immediate
'SELECT JSONOBJECT(JSONARRAY_AGG(JSONOBJECT(
col1,
col2,
col3,
col4,
col5,
col6,
....
....
)) as "data"
) as json FROM(
SELECT SUM((CASE
WHEN ((CASE
.....
....
.....
FROM ex_table AS ex
JOIN table1
ON ...
.....
WHERE a=b AND ' || filters || '
GROUP BY col)
) AB';
END
But as soon as I add more lines into above SQL query then it give an parsing error login an arbitrary line. There is nothing wrong with the syntax of my query. The only change I make is the length of the query adding more lines into it(eg. In my SELECT statement If I select onemore extra column this gives an parsing error)This happens only when I am using execute immediate to execute queries
What version or Teiid are you using? And what is your parsing exception?
If it is due to truncation, then you'll need to use a 9.1 or later release, which allows for longer evaluated sql strings - https://issues.jboss.org/browse/TEIID-4376

Oracle Pro*C Bulk Merge of records in C/C++ using host arrays

Using Oracle Pro*C in C/C++, we can use host arrays for managing bulk inserts into the EMP table as per following example:
struct
{
char ename[3][10];
int eno[3];
} emp_rec1;
struct
{
int dno[3];
} emp_rec2;
...
strcpy(emp_rec1.ename[0], "e1");
strcpy(emp_rec1.ename[1], "e2");
strcpy(emp_rec1.ename[2], "e3");
emp_rec1.eno[0] = 1964; emp_rec2.dno[0] = 5;
emp_rec1.eno[1] = 1974; emp_rec2.dno[1] = 5;
emp_rec1.eno[2] = 1985; emp_rec2.dno[2] = 5;
EXEC SQL INSERT INTO emp (ename, eno, dno)
VALUES (:emp_rec1, :emp_rec2);
Can I do a MERGE using EXEC SQL MERGE kind of to try an update first (if ename and eno exist) with dno getting updated, if does not exist then of course insert to do a bulk merge instead of trying to merge one record at a time, e,g, do a select first, of record exists, try an update else apply insert.
Please help with similar example and syntax for bulk merge as embedded SQL in Pro*C.
I'm looking at pro*c code that uses the merge command. It does the following.
EXEC SQL
EXECUTE
BEGIN
MERGE INTO aTable
USING
...
WHEN MATCHED THEN
UPDATE SET
...
END;
END-EXEC;

SQLite - How to use it at terminal level & C++ application?

i am new to sqlite and I just recently installed it. I am familar with mysql but I need to use sqlite as I am using it for a C++ application that I am going to create.
Question 1:
I type this at my command line terminal
root#ubuntu:/home/baoky/version1.2/Assignment 2# sqlite abeserver.db
then I saw this output
sqlite>
So i type .h and i see a list of help commands
But i wanna create a table
sqlite> .databases
seq name file
--- --------------- ----------------------------------------------------------
0 main /home/baoky/version1.2/Assignment 2/abeserver.db
1 temp /var/tmp/sqlite_hjT3FEefcAHRPhn
in my main database
How do i execute this sql command at terminal level
CREATE TABLE abe_account (
username TEXT,
name TEXT,
department TEXT,
password TEXT
);
Question 2:
How do I insert record into the table abe_account using C++
Question 3:
How do I retrieve records from table abe_account and assign it to a string using C++
Sorry I tried google around and search around stack overflow, I am still confused with the usage, if its mysql, it would be much simple for me.
Question 2:
Question 3:
Let me google it for you, friend: An Introduction To The SQLite C/C++ Interface.
If you are using the sqlite terminal, you can just type SQL there, and it will be executed.
A typical cycle of work from your C++ code will look something like this:
sqlite3 * db;//database
sqlite3_stmt * stmt;//sql statement
sqlite3_open( "database.db", & db );//opening database
sqlite3_prepare( db, "SELECT something FROM something else;", -1, &stmt, NULL );//preparing the statement
sqlite3_step( stmt );//executing the statement
while( sqlite3_column_text( stmt, 0 ) )
{
char * str = (char *) sqlite3_column_text( stmt, 0 );///reading the 1st column of the result
//do your stuff
sqlite3_step( stmt );//moving to the next row of the result
}
sqlite3_finalize(stmt);
sqlite3_close(db);
You can easily google the functions to learn about their arguments and what they do in-detail.
To create a new database, just connect to it:
$ sqlite3 your_database_file
This will create your database in the file your_database_file. If this file already exists, the command will open it.
Then you can execute CREATE TABLE or any other SQL.

c++ how to make two statement sql work with OLEDB?

I have the following SQL statement:
USE "ws_results_db_2011_09_11_09_06_24";SELECT table_name FROM INFORMATION_SCHEMA.Tables WHERE table_name like 'NET_%_STAT' order by table_name
I am using the following C++ code to execute it:
IDBCreateCommandPtr spDBCreateCommand = GetTheDBCreateCommandPointer();
ICommandTextPtr spCommandText;
spDBCreateCommand->CreateCommand(NULL, IID_ICommandText, reinterpret_cast<IUnknown **>(&spCommandText));
spCommandText->SetCommandText(DBGUID_SQL, GetTheQueryText());
IRowsetPtr spRowset;
spCommandText->Execute(NULL, IID_IRowset, NULL, NULL, reinterpret_cast<IUnknown **>(&spRowset));
RowHandles hRows(spRowset, 0);
ULONG rowCount;
ULONG maxRowCount = 1;
spRowset->GetNextRows(DB_NULL_HCHAPTER, 0, maxRowCount, &rowCount, hRows.get_addr());
Two notes:
Error handling is omitted for brevity
RowHandles implements the RAII concept for HROW *
Anyway, I fail to execute the two SQL statements. What happens is that spCommandText->Execute returns S_OK, but sets spRowset to NULL.
If I execute the same spCommandText->Execute the second time (by moving back the instruction pointer during the debugging session), then a valid IRowset pointer is returned - I successfully obtain the correct column information using it. But spRowset->GetNextRows sets rowCount to 0 and returns DB_S_ENDOFROWSET - no luck.
The code is working fine when I execute a single SQL statement.
What am I doing wrong?
Thanks.
It is up to the client to split the sql commands - isql does this on the ; ie you are asking for two commands the use and the select.
So the fix is to do the two commands by separate sets of CreateCommands and execute.
Also note in this case you can do the commands as one SQL statement
SELECT table_name FROM ws_results_db_2011_09_11_09_06_24.INFORMATION_SCHEMA.Tables
WHERE table_name like 'NET_%_STAT'
order by table_name