Call procedure on Oracle 11.2.0 via JayDeBeApi in Python - python

I am trying to call dbms_random.seed(42) on my DB, see ref. I need to use python and the JayDeBeApi connector. So far I've only been able to execute select statement without issue. I fail to understand what I am doing wrong.
It seems that JayDeBeApi does not provide the callproc method, so I cannot use it:
AttributeError: 'Cursor' object has no attribute 'callproc'
I've naively tried:
conn = jaydebeapi.connect('oracle.jdbc.driver.OracleDriver',
['jdbc:oracle:thin:#server:1521/dbname', 'user', 'password'])
curs = conn.cursor()
sql="exec dbms_random.seed(42)"
curs.execute(sql)
but this leads to: Error: ORA-00900: invalid SQL statement
I've tried two solutions which seems to have correct syntax, but since the generator is not deterministic, I believe they actually failed:
Using begin/end:
sql="begin dbms_random.seed(42); end;"
curs.execute(sql)
Using call:
sql="{ call dbms_random.seed(42) }"
curs.execute(sql)
So my question is: how do I call dbms_random.seed(42) on Oracle using JayDeBeApi ? As a side question how do I check that a statement has actually failed to execute (no exception was thrown and return value for execute is undefined.)
Update:
In fact the seed initialization is working as expected, since the results are what I expect for:
sql="SELECT DBMS_RANDOM.value FROM dual"
curs.execute(sql)
data = curs.fetchall()
print(data)
However I still see some odd behavior for my random query selection:
SELECT *
FROM (
SELECT *
FROM table
ORDER BY DBMS_RANDOM.RANDOM)
WHERE rownum < 21;
For some reason in the latter case, the DBMS_RANDOM.RANDOM is actually random...

After multiple trial and error, I believe this is just a side effect. Since I was not doing the cleanup pass:
curs.close()
conn.close()
jpype.shutdownJVM()
The query would lead to somewhat undefined behavior. Now that I have a proper cleanup code, I am getting deterministic results when calling multiples times my python script.

Related

How to fetch warnings from a django mysql query?

I'm trying to get a list of warnings after a mySQL query, using Django admin. I can see from the documentation here that it's possible to record warnings by setting connection.get_warnings to true. But I can't find anything explaining how to read those warnings.
I do not want to throw an exception - I am deleting items from the database using a DELETE IGNORE statement and want to get all instances of deletions that failed (due to external keys, etc.)
I've tried returning the result of the execute function itself (just gave me a number) and calling fetchwarnings() on the cursor (threw a "Cursor object has no attribute fetchwarnings" error).
I'm still new to both Python and Django. I'm looking through all the documentation I can find but can't find anything that works.
from django.db import connection
query = "{query here}"
connection.get_warnings = True
with connection.cursor() as cursor:
cursor.execute(query) <-- Returns a number
return cursor.fetchwarnings() <-- Throws an error

Using Python and mySQL (and windows as OS), cursor.execute() is returning no results but it is connecting

So I have an issue very similar to this question, but a bit different.
I am calling cursor.execute(sqlString) on a piece of sql that works fine when I run it directly on the mysql workbench. When I run the code however I get no result set.
I have exactly the same issue symptons as stated in the link and I have tried the linked solutions but it turns out that I do not have the same issue.
my _stored_results[] is empty when returning.
I am using the code in a try/except block, I have another python program that uses the same code to load a csv into a my mySQL db and it works dandy.
The code where I am having the issue is within an #app.route if that makes any differnce.
My code looks like this:
def functionName() :
try:
import mysql.connector
from mysql.connector import errorcode
cnx = mysql.connector.connect(user=init["dbDetails"][0], password=init["dbDetails"][1], host=init["dbDetails"][2], database=init["dbDetails"][3])
cur = cnx.cursor()
cur.close() #I deffo don't need the two lines below but they were added for a sanity check, just to make sure the cur was not being read from any other code.
cur = cnx.cursor() # and this one obviously
sqlString = 'CALL `schemaName`.`getProcedureName_sp`(1, 1, 0)'
cur.execute(sqlString, multi=True) # tried it here without the multi=True and got the msg telling me to use it.
getSomeDetails = cur.fetchall()
cnx.commit() # probably don't need to commit here I am just reading from the dB but I am trying anything as I have no idea what my issue might be.
return render_template('success.html')
except Exception as e:
return render_template('error.html', error = str(e))
finally:
cur.close()
cnx.close()
I am so baffled as I have this same code working in several places.
So I was beating my head against the wall with this, and when I couldn't get anywhere, I just decided to leave it and move on, then come back with a fresh mind. Well... It worked, kinda.
So I haven't found the solution but I have found a work around that does the job and might even shed some light as to what is actually happening in my code.
I decided that as the fetchall() method was what was causing me the trouble I should try to circumvent it.
I probed the cursor(cur) just before the fetchall() method was called and saw that cur._rows contains the results from the SQL call.
So I changed the line
getSomeDetails = cur.fetchall()
to
if len(cur._rows) > 0 :
getSomeDetails = list(cur._rows[0]) #I only ever expect one result in this query
#getSomeDetails should now have the row I am looking for
getSomeDetails[0] #gets me the field I am looking for
and now my variable getSomeDetails has the return values from the procedure call
They are however not in the nice format that I should have gotten them from the fetchall() function, so I had to do some processing, I had to ensure that I was getting some values back and I noted that these values were returned in a tuple
I have come across this issue on two different machines running two different OS's and two different versions of python (Windows 7 with Python 2.7 and Windows 10 with Python 3) both pieces of code were different so obviously infact I was using two different MySQL libraries so the actual code for the fix was slightly different in both cases but I am now in both cases getting data from my DB into variables in Python, so that's cool.
However, this is a hack and I am aware of that, I would rather be using the proper function cur.fetchall() so I am still open to suggestions of what could be going wrong here.

Output parameters are not populated

I have the following code:
conn = pymssql.connect(server, user, password, database)
cursor = conn.cursor()
id_new_field = pymssql.output(int)
res = cursor.callproc('NewField', ('Test',id_new_field))
conn.commit()
conn.close()
print(id_new_field.value)
print(res)
Unfortunately my output parameter isn't populated with the id of the field, although the stored procedure is executed correctly. The output ist always 'None'.
I think the problem is, that autocommit ist set to false in my example, am i right?
But i can't set autocommit to true because the stored procedure is raising an error when it isn't executed inside a transaction (It's a vendor SP and i can't alter the SP).
So, my workarount for now is, to use .execute() instead of .callproc() and writing raw sql into my python script. It's awful. ;)
Is there any chance to use .callproc() with autocommit = false?
Or do i have to do it completely different?
I also got None when I did
print(id_new_field.value)
but I was able to retrieve the value by simply indexing into res tuple:
print(res[1])
(Tested with Python 2.7.11 and pymssql 2.1.1.)

Python psycopg2 PostgreSQL attemp to deallocate

I wanted to know if it's possible to attempt to deallocate a PostgreSQL prepared statement before trying to open it
at the moment I am using the following code to deallocate all prepared statements
cur_deallocate = gv_pgsql.cursor()
cur_deallocate.execute("deallocate all")
cur_users = gv_pgsql.cursor()
cur_users.execute("prepare cur_users as " +
"select * from users")
this works however if there is another prepared statement that I still need in a separate function then it will be closed as well. However if I use deallocate cur_users then the program will crash with the error that it can't deallocate a prepared statement that doesn't exist.
Is there a way around this? to attempt to deallocate and if it fails then prepare the statement
Catch the error in an except block, or see if it exists first using pg_prepared_statements view: enter link description here
In our installation statement names are stored in lower case
def safe_deallocate(self, statement_name):
curs.execute(
"select true from pg_prepared_statements where name = lower(%s)", (statement_name,))
if curs.rowcount:
curs.execute("deallocate {}".format(statement_name))

Executing script by using function callproc from cx_Oracle module in python 2.7.5

I'm relatively new to Python.
I'm currently working on SQL statement execution in Oracle DB.
When I execute query:
query = 'select * from table'
cursor.execute(query)
result = cursor.fetchall()
everything is going fine, but when I try to execute script:
script in plain text:
begin
SIEBEL_DBA.X_DR_DEPLOY(id => '1-4NANEI', env_code => 'SVE_SIT');
end;
/
code from script
script = "begin\nSIEBEL_DBA.X_DR_DEPLOY(id => '1-4NANEI', env_code => 'SVE_SIT');\nend;"
cursor.execute(script)
result = cursor.fetchall()
I get an exception, that this is not a query, but still this script has worked.
So from what I've googled, looks like I should use callproc function:
cursor.callproc['SIEBEL_DBA.X_DR_DEPLOY',{'id' : '1-4NANEI', 'env_code' : 'SVE_SIT'}]
connection.commit()
result = cursor.fetchall()
When I'm executing this statement, I'm also getting exception, but this time nothing has been changed in DB:
'builtin_function_or_method' object has no attribute 'getitem'
Could someone please point where I'm not correct and how should I modify statement so it would be working.
Huge thanks in advance!
RESOLUTION:
I was frustrated by the syntax and the complexity of callproc and callfunc functions.
I've found good resource: http://dbaportal.eu/sidekicks/sidekick-cx_oracle-code-paterns/#part1
in this link I found all needed info and examples on how to work with cx_Oracle library.
at the end I just needed to modify a bit my code:
cursor.callproc('SIEBEL_DBA.X_DR_DEPLOY', ['1-4NANEI', 'SVE_SIT'])
and the needed part was done, I didn't need to specify any return type, as script that I'm executing doesn't return any value, it just sets it.
The exception is because you are using [ ] where you should be using ():
cursor.callproc('SIEBEL_DBA.X_DR_DEPLOY',{'id' : '1-4NANEI', 'env_code' : 'SVE_SIT'})
Keep in mind the return type is required:
Cursor.callfunc(name, returnType, parameters=[], keywordParameters =
{})
Call a function with the given name. The return type is specified in
the same notation as is required by setinputsizes(). The sequence of
parameters must contain one entry for each argument that the function
expects. Any keyword parameters will be included after the positional
parameters. The result of the call is the return value of the
function.

Categories

Resources