Skip to content

Commit

Permalink
allow execution of queries without prepared statements
Browse files Browse the repository at this point in the history
  • Loading branch information
tdawber committed Jan 19, 2017
1 parent c2a160f commit a1f8d3c
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 7 deletions.
25 changes: 18 additions & 7 deletions jaydebeapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,18 +488,29 @@ def _set_stmt_parms(self, prep_stmt, parameters):
# print (i, parameters[i], type(parameters[i]))
prep_stmt.setObject(i + 1, parameters[i])

def execute(self, operation, parameters=None):
def execute(self, operation, parameters=None, use_prepared_statements=True):
if self._connection._closed:
raise Error()
if not parameters:
parameters = ()
self._close_last()
self._prep = self._connection.jconn.prepareStatement(operation)
self._set_stmt_parms(self._prep, parameters)
try:
is_rs = self._prep.execute()
except:
_handle_sql_exception()

if use_prepared_statements:
self._prep = self._connection.jconn.prepareStatement(operation)
self._set_stmt_parms(self._prep, parameters)

try:
is_rs = self._prep.execute()
except:
_handle_sql_exception()
else:
self._prep = self._connection.jconn.createStatement()

try:
is_rs = self._prep.execute(operation)
except:
_handle_sql_exception()

if is_rs:
self._rs = self._prep.getResultSet()
self._meta = self._rs.getMetaData()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
Expand All @@ -25,23 +26,30 @@ public final void mockExceptionOnRollback(String className, String exceptionMess

public final void mockExceptionOnExecute(String className, String exceptionMessage) throws SQLException {
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
Statement mockStatement = Mockito.mock(Statement.class);
Throwable exception = createException(className, exceptionMessage);
Mockito.when(mockPreparedStatement.execute()).thenThrow(exception);
Mockito.when(mockStatement.execute(Mockito.anyString())).thenThrow(exception);
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
Mockito.when(this.createStatement()).thenReturn(mockStatement);
}

public final void mockType(String sqlTypesName) throws SQLException {
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
Statement mockStatement = Mockito.mock(Statement.class);
Mockito.when(mockPreparedStatement.execute()).thenReturn(true);
Mockito.when(mockStatement.execute(Mockito.anyString())).thenReturn(true);
mockResultSet = Mockito.mock(ResultSet.class, "ResultSet(for type " + sqlTypesName + ")");
Mockito.when(mockPreparedStatement.getResultSet()).thenReturn(mockResultSet);
Mockito.when(mockStatement.getResultSet()).thenReturn(mockResultSet);
Mockito.when(mockResultSet.next()).thenReturn(true);
ResultSetMetaData mockMetaData = Mockito.mock(ResultSetMetaData.class);
Mockito.when(mockResultSet.getMetaData()).thenReturn(mockMetaData);
Mockito.when(mockMetaData.getColumnCount()).thenReturn(1);
int sqlTypeCode = extractTypeCodeForName(sqlTypesName);
Mockito.when(mockMetaData.getColumnType(1)).thenReturn(sqlTypeCode);
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
Mockito.when(this.createStatement()).thenReturn(mockStatement);
}

public final ResultSet verifyResultSet() {
Expand Down
10 changes: 10 additions & 0 deletions test/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# <http://www.gnu.org/licenses/>.

import jaydebeapi
from jaydebeapi import OperationalError

import os
import sys
Expand Down Expand Up @@ -207,6 +208,15 @@ def test_execute_different_rowcounts(self):
cursor.execute("select * from ACCOUNT")
self.assertEqual(cursor.rowcount, -1)

def test_sql_exception_on_execute(self):
cursor = self.conn.cursor()
try:
cursor.execute("dummy stmt", use_prepared_statements=False)
except jaydebeapi.DatabaseError as e:
self.assertEquals(str(e).split(" ")[0], "java.sql.SQLException:")
except self.conn.OperationalError as e:
self.assertEquals("syntax" in str(e), True)

class SqliteTestBase(IntegrationTestBase):

def setUpSql(self):
Expand Down
9 changes: 9 additions & 0 deletions test/test_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ def test_sql_exception_on_execute(self):
except jaydebeapi.DatabaseError as e:
self.assertEquals(str(e), "java.sql.SQLException: expected")

def test_sql_exception_on_no_prepared_execute(self):
self.conn.jconn.mockExceptionOnExecute("java.sql.SQLException", "expected")
cursor = self.conn.cursor()
try:
cursor.execute("dummy stmt", use_prepared_statements=False)
fail("expected exception")
except jaydebeapi.DatabaseError as e:
self.assertEquals(str(e), "java.sql.SQLException: expected")

def test_runtime_exception_on_execute(self):
self.conn.jconn.mockExceptionOnExecute("java.lang.RuntimeException", "expected")
cursor = self.conn.cursor()
Expand Down

1 comment on commit a1f8d3c

@fmcmac
Copy link

@fmcmac fmcmac commented on a1f8d3c Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I am working on Apache Drill using the jdbc driver via jaydebeapi. We have the issue of queries becoming wrapped where not select statements. E.g. "SHOW DATABASES" represents to Drill as "SELECT * FROM (SHOW DATABASES) LIMIT 0. This appears to be related to Prepared Statements. I can't see if this disable functionality here is usable yet (presumably "use_prepared_statements=False")? Is a solution available here? Regards.

Please sign in to comment.