When do a PREPARE QUERY fails in PRO C?
EXEC SQL AT :db_id PREPARE QUERY FROM :sql_query;
bool sql_status = (sqlca.sqlcode == OERR_ORACLE_SUCCESS);
if (sql_status)
{
}
else
{
}
I don't have this problem until recently, The code was working fine the PREPARE QUERY is working fine (going into if loop_, but all of a sudden it failed, and is not working after that (going into else loop).
Nothing has changed and it's the same binary.
Does anybody face a similar problem in the past?
I've written a LOT of pro*c in the past, and over time realized that you don't want to be checking the return code of the PREPARE statement as it never returns any value. Here is what I mean:
The PREPARE sqlca.sqlcode value is the return code of the statement that ran immediately BEFORE the PREPARE statement. In other words, if you check the output of the PREPARE statement and the statement that executed right before the PREPARE statement fails, then the return code of the prepare is failed. If the previous statement succeeded, then the PREPARE appears to have succeeded.
In other words, the prepare sqlca.sqlcode value is basically nothing (it doesn't ever fail on its own). So if the PREPARE is now failing, check the statement that executed right before the PREPARE statement and ensure you're checking the sqlca.sqlcode value of that one. My bet is that the previous statement is failing, and the error returned relates to that statement. Make sense?
-Jim
Related
I'm trying to code a multi-threaded program using VB.NET. It's a simple program: go to a database, get a row, process some back-end, then update the row and set it as "processed = true". Because there is so much data, I'm planning to do a multi-threaded program for it.
SELECT... FOR UPDATE doesn't seem to work in a transaction for some odd reason, and so I've decided to pre-emptively mark the row as "being read = TRUE", then process it from there.
Is it possible to update the row, then retrieve the row ID from the same SQL statement?
I've tried using these SQL statements together:
Dim sqlUpdateStatement As String = "SET #uid := 0;UPDATE process_data SET reading = TRUE, idprocess_data = (SELECT #uid := idcrawl_data) WHERE reading IS NOT TRUE AND processed IS NOT TRUE LIMIT 1;SELECT #uid;"
but it tells me that there was a fatal error encountered during command execution.
Any ideas?
EDIT
After some testing, I've come to the conclusion that you can't use MySQL variables when performing updates in VB.Net. Is this true? And if so, is there a workaround?
I eventually took the time to debug the SELECT FOR UPDATE portion of my code to get it to work on a Transaction basis. Thanks everyone for their time!
I came across a stored procedure which does this:
DECLARE #DebugLogging BIT = dbo.fnIsDebugLoggingEnabled();
IF (#DebugLogging = 1)
BEGIN
-- some verbose logging information here...
END
based on whether a debug logging is enabled or not, which is an output given by scalar function dbo.fnIsDebugLoggingEnabled().
I checked the create script for that function and I think it will always return 0. Maybe I am wrong. Can someone check if I am thinking correctly or not?
I am thinking --> why would someone put efforts to do something for a condition that will never occur?
Script for the function is:
CREATE FUNCTION [dbo].[fnIsDebugLoggingEnabled]()
RETURNS BIT
AS
BEGIN
RETURN 0;
END
I ran select dbo.fnIsDebugLoggingEnabled() and it indeed returned 0.
Your observation is correct; the returned value will always be zero so the verbose logging will not occur.
I can't say why the developer chose to implement the debugging flag this way but it may be a deployment option where different versions of the function are created depending on the selection. Personally, I'd store configurable values like this in a table.
General procedure are no return value then stored procedure why return?
As you wrote, stored procedure do not return any value. They run from its beginning to its end and, when no more statements to execute, they get back to the invoking code.
The use of a RETURN statement within a stored procedure is when you don't want to continue its processing. Example:
You have a stored procedure that receives 3 parameters and returns 2, a result and a status code (e.g. SUCCESS or FAIL). The procedure first checks that all the received parameters are present and within legal values and, if not present or illegal values are found, you don't want to proceed and simply RETURN to the invoking code with the applicable status code. You do this through the RETURN command.
Hope this is clear.
I'm not sure what is your problem. You mean why SP need a return statement?
Because in some case, we need process cross table operation and complex calculation. If we need a result we should return a result from SP.
In some aggregate calculation we need a final result, but the aggregate SQL is very complex. So we need use the SP instead of general SQL statement then return a result.
I am trying to build a scenario that would allow me to expose additional data from a server (for case-demo purposes). The server calls a vulnerable SQL code:
EXEC my_storeProc '12345'
where "12345" (not the single quotes) is the parameter. This performs a SELECT statement. I would like to eliminate this execution and instead call my own select statement, however the server side code will only accept the first select statement called, contained within the aforementioned EXEC call. Calling the second statement is easy:
EXEC my_storeProc '12345 ' select * from MySecondTable--
(the -- at the end will block the closing single quote added by the server to prevent errors). My problem is that although there are 2 select statements, the server will only parse the first one. Is there a way to cancel the first EXEC call without throwing an error so that the second one would be taken instead? Perhaps even a UNION but there isn't much I can do with only one variable open to exploit (variable being 12345 in this case).
You have to think of how it will be executed, specifically you want it called so it doesn't raise an exception and put the kabosh on the whole statement. You can't set the result to always true with a proc call, so there is no real way escape the proc. Instead, you'll want to slip a second command in, Your desired code looks like;
exec my_Storeproc '1234'; select * from mysecondtable
So we need to close the quotes, and make a new statement. That would mean the string with the insert needs to be;
1234'; select * from mysecondtable where 1 = '1
There is a flaw in this, whatever command you are executing is not being returned to the UI. To get the data you'll have to add a server connection to the second command.
To make the second command unnecessary you would have to inject code into the proc, which is a non starter since the proc is already complied and sql injection relies on confusing the compiler as to what is data and what is commands. For a more verbose explanation of that check out this answer:
https://security.stackexchange.com/a/25710
I'm working on an SQLite[3.6.20]-based C library, and I have encountered a behavior I don't understand. When it comes time to close the database connection, I perform a preemptive rollback, and then I attempt to use sqlite3_next_stmt() to iterate over all unfinalized prepared statements and finalize them:
sqlite3_stmt *stmt;
for (stmt = sqlite3_next_stmt(db, NULL);
stmt;
stmt = sqlite3_next_stmt(db, stmt)) {
sqlite3_finalize(stmt);
}
This indeed does iterate over several statements, and with a little instrumentation I can confirm that sqlite3_finalize() returns SQLITE_OK for each one.
In certain test cases, however, when I thereafter attempt to close the DB, I get SQLITE_BUSY (code 5) with an explanation that there are unfinalized statements. And indeed, if at that point I call sqlite3_next_stmt() again, it returns a statement that my program likely did prepare, but which was not among those previously returned by sqlite3_next_stmt().
So, am I wrong to think that the unfinalized statement should have been provided by sqlite3_next_stmt() on the first pass? Is there something extra I should do to ensure that my statements can be cleaned up this way?
You shouldn't trust stmt to contain anything meaningful (even to sqlite3_next_stmt()) after it's been finalized.
Instead:
while (stmt = sqlite3_next_stmt(db, NULL))
{
sqlite3_finalize(stmt);
}