Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New drivers #1279

Merged
merged 5 commits into from
Sep 23, 2024
Merged

New drivers #1279

merged 5 commits into from
Sep 23, 2024

Conversation

phenobarbital
Copy link
Owner

@phenobarbital phenobarbital commented Sep 23, 2024

  • Oracle driver based on oracledb
  • MongoDB driver using Motor

Summary by Sourcery

Add new drivers for Oracle and MongoDB to support asynchronous database operations. Enhance the JDBC driver with configurable JVM memory settings and improve error handling. Update dependencies and add a new example test script for JDBC connections.

New Features:

  • Introduce an Oracle driver for asynchronous interaction with Oracle databases using the oracledb library.
  • Add a MongoDB driver for asynchronous interaction with MongoDB using the Motor library.

Enhancements:

  • Enhance the JDBC driver to support configurable maximum memory allocation for the JVM.
  • Improve error handling and logging across the Oracle, MongoDB, and JDBC drivers.

Build:

  • Update the setup.py to include JPype1 as a dependency for the JDBC driver and upgrade the oracledb dependency to version 2.4.1.

Tests:

  • Add a new example test script for testing JDBC connections with PostgreSQL.

Chores:

  • Bump the version of the asyncdb library from 2.9.1 to 2.9.2.

Copy link
Contributor

sourcery-ai bot commented Sep 23, 2024

Reviewer's Guide by Sourcery

This pull request introduces new asynchronous drivers for Oracle and MongoDB, enhances the JDBC driver with improved error handling and resource management, updates dependencies, and adds a new example script for testing JDBC with PostgreSQL.

File-Level Changes

Change Details Files
Implemented an asynchronous Oracle driver using oracledb.
  • Added class-level docstring for Oracle driver.
  • Updated the initialization method to include detailed docstring and parameter handling.
  • Implemented asynchronous connection handling with detailed error logging.
  • Added methods for executing SQL statements and handling transactions asynchronously.
  • Implemented methods for schema switching and query execution with error handling.
asyncdb/drivers/oracle.py
Implemented an asynchronous MongoDB driver using Motor.
  • Added class-level docstring for MongoDB driver.
  • Updated the initialization method to handle DSN and connection parameters.
  • Implemented asynchronous connection handling with error logging.
  • Added methods for executing operations on collections asynchronously.
  • Implemented query methods for retrieving documents with error handling.
asyncdb/drivers/mongo.py
Enhanced JDBC driver with additional features and error handling.
  • Refactored the initialization method to include max_memory parameter.
  • Improved connection handling with detailed error logging and JVM management.
  • Updated query execution methods to use thread executor for asynchronous operations.
  • Enhanced close method to ensure proper JVM shutdown and resource cleanup.
asyncdb/drivers/jdbc.py
Updated dependencies and versioning in setup and version files.
  • Updated oracledb dependency to version 2.4.1.
  • Added JPype1 dependency for JDBC support.
  • Incremented asyncdb version to 2.9.2.
setup.py
asyncdb/version.py
Added new example script for testing JDBC with PostgreSQL.
  • Created a new test script for JDBC PostgreSQL connection and queries.
  • Included example queries and connection handling in the script.
examples/test_jdbc_pg.py

Tips
  • Trigger a new Sourcery review by commenting @sourcery-ai review on the pull request.
  • Continue your discussion with Sourcery by replying directly to review comments.
  • You can change your review settings at any time by accessing your dashboard:
    • Enable or disable the Sourcery-generated pull request summary or reviewer's guide;
    • Change the review language;
  • You can always contact us if you have any questions or feedback.

@phenobarbital phenobarbital merged commit ac2905e into master Sep 23, 2024
1 of 2 checks passed
@phenobarbital phenobarbital deleted the new-drivers branch September 23, 2024 12:01
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @phenobarbital - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider implementing connection pooling for the JDBC driver to improve performance and resource management.
  • Standardize error handling across all drivers to ensure consistent behavior and easier debugging.
Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟡 Security: 1 issue found
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment to tell me if it was helpful.

self._connection.cursor,
executor=self._executor
)
await self._thread_func(
Copy link
Contributor

Choose a reason for hiding this comment

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

🚨 issue (security): Use parameterized queries to prevent SQL injection

In the execute and execute_many methods, ensure that you're using parameterized queries instead of string formatting for SQL statements. This is crucial for preventing SQL injection vulnerabilities.

fetchrow = fetch_one
fetchone = fetch_one

async def write(
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Consider refactoring the write method for better maintainability

The write method is quite complex. Consider breaking it down into smaller, more focused functions. This would improve readability, maintainability, and make it easier to test individual components of the write operation.

async def write(self, data):
    return await self._write_operation(data)

async def _write_operation(self, data):
    # Existing write logic goes here

return self

connect = connection

async def close(self, timeout: int = 10) -> None:
async def close(self, timeout: int = 5) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Move JVM shutdown logic to a separate method

The JVM shutdown logic in the close method is quite complex. Consider moving this logic into a separate method for better organization and potential reuse in other parts of the driver.

async def close(self, timeout: int = 5) -> None:
    await self._shutdown_jvm(timeout)

async def _shutdown_jvm(self, timeout: int) -> None:
    print("JVM started: ", jpype.isJVMStarted())
    if not self._connected or not self._connection:
        return

Comment on lines 108 to 110
_jvmArgs.append("-Djava.class.path=" + path)
_jvmArgs.append("-Xmx12000m")
_jvmArgs.append(f"-Xmx{self.max_memory}m")
_jvmArgs.append("-Dfile.encoding=UTF8")
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (code-quality): We've found these issues:

Suggested change
_jvmArgs.append("-Djava.class.path=" + path)
_jvmArgs.append("-Xmx12000m")
_jvmArgs.append(f"-Xmx{self.max_memory}m")
_jvmArgs.append("-Dfile.encoding=UTF8")
_jvmArgs.append(f"-Djava.class.path={path}")
_jvmArgs.extend((f"-Xmx{self.max_memory}m", "-Dfile.encoding=UTF8"))

if "does not exist" in str(ex):
raise DriverError(
f"Database does not exist: {self._params.get('database')}"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (code-quality): Explicitly raise from a previous error (raise-from-previous-error)

Suggested change
)
) from ex

Comment on lines +335 to +338
if not self._database:
raise DriverError(
"No database selected. Use 'use' method to select it."
)
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (code-quality): Hoist conditional out of nested conditional (hoist-if-from-if)

Suggested change
if not self._database:
raise DriverError(
"No database selected. Use 'use' method to select it."
)
if not self._database:
raise DriverError(
"No database selected. Use 'use' method to select it."
)

Comment on lines +380 to +383
if not self._database:
raise DriverError(
"No database selected. Use 'use' method to select it."
)
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (code-quality): Hoist conditional out of nested conditional (hoist-if-from-if)

Suggested change
if not self._database:
raise DriverError(
"No database selected. Use 'use' method to select it."
)
if not self._database:
raise DriverError(
"No database selected. Use 'use' method to select it."
)

result = None
if not self._database:
self._database = self.use(database=self._database_name)
if not self._database:
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): We've found these issues:

result = None
if not self._database:
self._database = self.use(database=self._database_name)
if not self._database:
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): We've found these issues:


# Build bulk operations
operations = []
if if_exists == 'replace':
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): We've found these issues:


Explanation

Python has a number of builtin variables: functions and constants that
form a part of the language, such as list, getattr, and type
(See https://docs.python.org/3/library/functions.html).
It is valid, in the language, to re-bind such variables:

list = [1, 2, 3]

However, this is considered poor practice.

  • It will confuse other developers.
  • It will confuse syntax highlighters and linters.
  • It means you can no longer use that builtin for its original purpose.

How can you solve this?

Rename the variable something more specific, such as integers.
In a pinch, my_list and similar names are colloquially-recognized
placeholders.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant