Support of various databases
Support for Different Databases
One of the primary objectives when developing the ORM system was to ensure support for multiple databases, such as PostgreSQL and MySQL. This task required careful planning and implementation to provide adaptability to various database specifications. The implementation of this feature in the ORM system is based on using the "Strategy" pattern, which allows selecting the appropriate query implementation based on the type of database.
In the DatabaseManager
class, a mechanism is implemented that takes the database type and initializes the corresponding class for generating queries specific to that database. For example, the DataSourcePostgres
class is used for PostgreSQL, while the DataSourceMySql
class is used for MySQL. This approach allows developers to obtain the necessary SQL queries tailored to the chosen database.
The DataSourceContext
class is responsible for setting the strategy that the ORM system will use depending on the type of database. Strategies, in turn, contain all the necessary methods for working with a specific database, such as creating tables, executing queries for selection, insertion, updating, and deleting data.
Type Safety within the System
Type safety in the system is provided through generic types, such as DT
, which represent the database type (e.g., DatabasesTypes.POSTGRES
). This allows users to get the correct types at all stages of working with the ORM, significantly reducing the risk of errors and ensuring proper query formation and database operations.
These generic types pervade the entire project, ensuring correct typing, for instance, when changing the table structure or performing other database manipulations. This allows developers to use types specific to a particular database, enhancing the reliability and security of the system.
On-the-Fly Code Generation and Metaprogramming
One of the most interesting and complex parts of the implementation is metaprogramming. By using metaprogramming, the ORM system generates the required code on-the-fly based on the chosen database. This is necessary to, for example, offer users the correct parameters supported by a specific database in decorators (such as Index
).
Upon the initial run, the system generates the corresponding interfaces and hints for the selected database type, significantly simplifying the work with the ORM and preventing potential errors due to incorrect parameter usage.
For instance, the Index
decorator may have different options for PostgreSQL and MySQL, and the system automatically generates the appropriate interfaces for each database type using metaprogramming techniques such as reflection (Reflect API), dynamic type and interface creation, and managing the project's file structure to store generated code.
This approach not only enhances the flexibility of the system but also facilitates easy integration with different databases without the need for manual code rewriting.
In this section, I provided an overview of the key concepts and approaches used in implementing support for different databases.
Last updated