Why the same query is being executed two times with the two methods? - postgresql

def execCypher(conn:ext.connection, graphName:str, cypherStmt:str, cols:list=None, params:tuple=None) -> ext.cursor :
if conn == None or conn.closed:
raise _EXCEPTION_NoConnection
cursor = conn.cursor()
#clean up the string for modification
cypherStmt = cypherStmt.replace("\n", "")
cypherStmt = cypherStmt.replace("\t", "")
cypher = str(cursor.mogrify(cypherStmt, params))
cypher = cypher[2:len(cypher)-1]
preparedStmt = "SELECT * FROM age_prepare_cypher({graphName},{cypherStmt})"
cursor = conn.cursor()
try:
cursor.execute(sql.SQL(preparedStmt).format(graphName=sql.Literal(graphName),cypherStmt=sql.Literal(cypher)))
except SyntaxError as cause:
conn.rollback()
raise cause
except Exception as cause:
conn.rollback()
raise SqlExecutionError("Execution ERR[" + str(cause) +"](" + preparedStmt +")", cause)
stmt = buildCypher(graphName, cypher, cols)
cursor = conn.cursor()
try:
cursor.execute(stmt)
return cursor
except SyntaxError as cause:
conn.rollback()
raise cause
except Exception as cause:
conn.rollback()
raise SqlExecutionError("Execution ERR[" + str(cause) +"](" + stmt +")", cause)
I just want to understand that if the two execution calls (with preparedStat & buildCypher functions) do the same thing, why are both of them being executed in the same function with same parameters?

The two execution calls are not doing the same thing. SELECT * FROM age_prepare_cypher({graphName},{cypherStmt}) is just storing the graphName and cypherStmt into the session.
The buildCypher function does this, it doesn't even touch your cypherStmt:
def buildCypher(graphName:str, cypherStmt:str, columns:list) ->str:
if graphName == None:
raise _EXCEPTION_GraphNotSet
columnExp=[]
if columns != None and len(columns) > 0:
for col in columns:
if col.strip() == '':
continue
elif WHITESPACE.search(col) != None:
columnExp.append(col)
else:
columnExp.append(col + " agtype")
else:
columnExp.append('v agtype')
stmtArr = []
stmtArr.append("SELECT * from cypher(NULL,NULL) as (")
stmtArr.append(','.join(columnExp))
stmtArr.append(");")
return "".join(stmtArr)
Later on it must be getting the graphName and cypherStmt back out of the session to use. So it needs both of them to work.
See more at https://stackoverflow.com/a/75461986/6796081

Related

Python mysql.connector .fetchall() returns (redundant) data in different formats

I have this method to execute Queries:
def exeQuery(query, data, dbEdit ):
try:
myDatabase = mysql.connector.connect(**dbLoginInfo)
cursor = myDatabase.cursor()
except mysql.connector.Error as e:
print('[ERROR WHILE CONNECTING TO DATABASE]: ', e)
else:
if dbEdit == True:
if data == None:
res = cursor.execute(query)
myDatabase.commit()
else:
res = cursor.execute(query, data)
myDatabase.commit()
else:
if data == None:
cursor.execute(query)
res = cursor.fetchall()
else:
cursor.execute(query, data)
res = cursor.fetchall()
cursor.close()
myDatabase.close()
#print(type(res))
#print(res)
return res
And I call it here:
#app.route("/profil/delete", methods= ['POST'])
#token_required
def deleteProfil():
dicUser = decodeToken(request.args.get('token'))
profilName = request.args.get('profilName')
path = exeQuery('SELECT profilbild FROM Profil WHERE profilName = %s AND konto_email = %s', (profilName, dicUser['user']), False)
print(path)
return Response(status = 200)
It should print me ('pics/jj#gmail.de/DelProf.png',) once.
For some reason I get the right data but sometimes the formatting is changing. Everytime there was only one row in the database that fit to the query. These are the three outputs I got so far:
[('pics/jj#gmail.de/DelProf.png',), ('pics/jj#gmail.de/DelProf.png',), ('pics/jj#gmail.de/DelProf.png',), ('pics/jj#gmail.de/DelProf.png',)]
[('pics/jj#gmail.de/DelProf.png',)]
('pics/jj#gmail.de/DelProf.png',)
The method MySQLCursor.fetchall() returns a list of tuples. as mentioned here: https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-fetchall.html.
Even if there are no results it will return a list, but empty [].
If you got a list with repeated values, it's possible that your query it may found those matches.

Insert to postgres DB: invalid String format (parsing exception error)

I am creating a log db where I track execution steps and catch where it might or might not fail.
I am having issues inserting the Exceptions thrown to a DB.
I am calling an endpoint first in order then query a django database.
In this case I wanted to catch a mistake in the selection_query and thus being unable to fetch the data from the DB.
I want to log this message.
Example:
Exception catch
try:
select_query = "SELECT columnn from row"
cur.execute(select_query)
selected_vals = cur.fetchall()
except Exception as e:
response = insert_into_logging(message = f"{e}", logging_id = 3)
Error
File "/usr/lib/python3.6/json/decoder.py", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
This is because of the value passed in the message argument.
(message = f"{e}")
It is not insertable in the DB
The value of "e" is:
auto_close_alarm relation "row" does not exist
LINE 1: SELECT columnn from row
^
I tried to pass
str(e)
Value passed: identical output as above
repr(e.args[0])
Output: 'relation "row" does not exist\nLINE 1: SELECT columnn from row\n ^\n'
repr(e)
Value passed: UndefinedTable('relation "row" does not exist\nLINE 1: SELECT columnn from row\n ^\n',)
And multiple other ways but to no avail.
They all result in the same JSONDecodeError.
Basically the key problem is that this is not a valid String format for it to be able to be parsed in the DB.
All I need is a representation of this Exception error for it to be insertable
Flow of data:
insert function
def insert_into_logging(message, logging_id, date_time):
url = f"""url/insert-into-logging/"""
data = {
"message": message,
"logging_id": logging_id,
}
response = r.post(url, data=json.dumps(data, indent=4, sort_keys=True, default=str))
print(response)
return response.json()
Querying DB
def insert_to_logging(request):
from datetime import datetime, timedelta
if request.method != 'POST':
print(request.method)
return JsonResponse({'status':'error', 'message':'Client insertion only accepts post requests.' + str(request.method)})
today = datetime.today()
body = json.loads(request.body)
message = body.get('message')
logging_id = body.get('logging_id')
Logging.objects.create(message = message, logging_id = logging_id, time_stamp = today)
return JsonResponse({'status':'OK', 'message':'Logging successful'})
Django Model
class Logging(models.Model):
objects = GetOrNoneManager()
message = models.CharField(max_length=64, blank=True, null=True)
logging_id = models.IntegerField(blank=True, null=True)
time_stamp = models.DateTimeField(blank=True, null=True)
class Meta:
db_table = 'logging'

PostgreSQL, Get database exists with Npgsql

I cant get reliable checking for database existence in NET/Npgsql at my program startup.
Here is code:
Public Function dbExists(ByVal _dbName As String) As Boolean
Dim retval As Boolean = False
Using mCon As New NpgsqlConnection(String.Format( _
"Server={0};Port={1};User Id={2};Password={3};", _
dbserver, dbport, "postgres", dbpass))
Try
mCon.Open()
Using nCom = New NpgsqlCommand("SELECT 1 FROM pg_database WHERE datname='" + _dbName + "'", mCon)
retval = CBool(nCom.ExecuteScalar())
End Using
Catch ex As Exception
retval = False
End Try
End Using
Return retval
End Function
This function return True no matter database exists or not.
I also try with null checking on ExecuteScalar, getting Count(*) and all what I can without better result.
What to do to get it working?
Null checking on 'ExecuteScalar()' works for me (PostgreSQL 9.3 and Npgsql 2.0.12).
Are you checking 'ExecuteScalar() == null'?
ExecuteScalar will return a .NET null not DBNull.Value (since it is not a record with a null value, it signifies no matching result).
I'm not a VB person but here's how I achieved it in C#:
bool dbExists;
using (NpgsqlConnection conn = new NpgsqlConnection("Server=127.0.0.1;Port=5432;Database=postgres;User Id=postgres;Password=testpass"))
{
conn.Open();
string cmdText = "SELECT 1 FROM pg_database WHERE datname='temp'";
using (NpgsqlCommand cmd = new NpgsqlCommand(cmdText, conn))
{
dbExists = cmd.ExecuteScalar() != null;
}
}

Using DB2, "statement.executeQuery()" throws SqlEception only in my system

//Class UserProfileDBUtil.java
Connection conn = null;
PreparedStatement statment = null;
ResultSet rs = null;
try{
String sqlString = "select count(*) from "+AGENCY_SCHEMA_NAME+".AGENCY WHERE AGENCYCODE= ? and ENABLEDFLAG = ?";
conn = JDBCUtils.getConnection(JDBCUtils.WP_ODS);
statment = conn.prepareStatement(sqlString);
statment.setString(1, agencyCode.toUpperCase());
statment.setString(2, "Y");
rs =statment.executeQuery(); // SQL Error Line 42
while(rs.next())
{
if(rs.getInt(1) > 0 )
{
return true;
}
}
log.error("Agency for agency code "+agencyCode+" is not available or not active");
}
LOG :
com.ibm.db2.jcc.b.SqlException: DB2 SQL error: SQLCODE: -401, SQLSTATE: 42818, SQLERRMC: =
at com.ibm.db2.jcc.b.sf.e(sf.java:1680)
at com.ibm.db2.jcc.b.sf.a(sf.java:1239)
at com.ibm.db2.jcc.c.jb.h(jb.java:139)
at com.ibm.db2.jcc.c.jb.a(jb.java:43)
at com.ibm.db2.jcc.c.w.a(w.java:30)
at com.ibm.db2.jcc.c.cc.g(cc.java:161)
at com.ibm.db2.jcc.b.sf.n(sf.java:1219)
at com.ibm.db2.jcc.b.tf.gb(tf.java:1818)
at com.ibm.db2.jcc.b.tf.d(tf.java:2294)
at com.ibm.db2.jcc.b.tf.X(tf.java:508)
at com.ibm.db2.jcc.b.tf.executeQuery(tf.java:491)
at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.executeQuery(WSJdbcPreparedStatement.java:559)
at UserProfileDBUtil.isAgencyActive(UserProfileDBUtil.java:42)
The error you're getting is a -401, which means:
The data types of the operands for the operation operator are not
compatible or comparable.
I would check and make sure that the parameters you're passing in are using the right data types. If you catch the exception, you should be able to use the exceptions Message property to see what the operator is. See here for an example.

How to use Multiple resultsets with POSTGRES JDBC?

I am using JDBC on a PostgreSQL database.
When I query for an entity in a resultset, it returns 5 rows.
Related to that entity is another entity, for which I query while i am using a row in the above resultset.
When I execute this query, the above resultset is closed.
This means that it is allowing only 1 resultset to be active on 1 connection at a time.
Previously the same code was working perfect for Oracle DB server.
Is it that I need to ask the DB admin to configure the server to allow multiple resultsets?
Or to do some change in the code?
Or is it impossible to do it in postgre?
Here is the code for more details:
Connection conn = PTSConnection.getConnection();
Statement stmt = conn.createStatement();
ResultSet lines = stmt.executeQuery("SELECT LINEID,STARTSTOPID,ENDSTOPID FROM LINES"); **//first resultset is active**
while (lines.next()){
int lineId= lines.getInt(1);
Stop ss = StopStorage.getByID(lines.getInt(2));
Stop es = StopStorage.getByID(lines.getInt(3));
ResultSet stops = stmt.executeQuery("SELECT STOPID FROM STOPSINLINES WHERE LINEID=" + lineId); **//first resultset dies**
List<Stop> lineStops = new ArrayList<Stop>();
while(stops.next()){
Stop stop = StopStorage.getByID(stops.getInt(1));
lineStops.add(stop);
}
stops.close();
Line aLine = null;
ResultSet emergencyLine = stmt.executeQuery("SELECT CAUSE, STARTTIME, ENDTIME FROM EMERGENCYLINES WHERE LINEID =" + lineId);
if(emergencyLine.next()){
String cause = emergencyLine.getString(1);
Time startTime = emergencyLine.getTime(2);
Time endTime = emergencyLine.getTime(3);
aLine = new EmergencyLine(ss, es, cause, startTime, endTime, (Stop[]) lineStops.toArray(new Stop[lineStops.size()]));
} else {
aLine = new Line(ss, es, (Stop[]) lineStops.toArray(new Stop[lineStops.size()]));
}
emergencyLine.close();
LineRepository.getInstance().addLine(aLine);
}
lines.close();
The reason is not that you are using two resultsets on the same connection, but you are re-using the same Statement object for a new query. When you run executeQuery() on a Statement instance, any previous result will be closed (I'm surprised that your code did work with Oracle...)
Simply create a new Statement object before executing the second query:
Statement stmt = conn.createStatement();
Statement nestedStmt = conn.createStatement();
ResultSet lines = stmt.executeQuery("SELECT LINEID,STARTSTOPID,ENDSTOPID FROM LINES"); **//first resultset is active**
while (lines.next()){
...
ResultSet stops = nestedStmt.executeQuery("SELECT STOPID FROM STOPSINLINES WHERE LINEID=" + lineId); **//first resultset dies**
List lineStops = new ArrayList();
while(stops.next()){
Stop stop = StopStorage.getByID(stops.getInt(1));
lineStops.add(stop);
}
stops.close();
...
ResultSet emergencyLine = nestedStmt.executeQuery("SELECT CAUSE, STARTTIME, ENDTIME FROM EMERGENCYLINES WHERE LINEID =" + lineId);
if(emergencyLine.next()){
String cause = emergencyLine.getString(1);
....
}
emergencyLine.close();
And don't for get to properly close all Statements and ResultSets !