Resources and tips to help aspiring entrepreneurs explore and discover new business opportunities.
From Ruby to SQL
Arel is an AST manager used in ActiveRecord to create SQL query. Every SQL statements are represented as ruby code in Arel. Because of this, it enable to write a complicated SQL query without using raw SQL string. But it’s not recommended to use Arel in the application because it’s a private API.
I’ll dive into the internal of Arel in this article. I’ll explain how it works when generating SQL with simple code example.
I’m not an expert of this subject. Please correct me if i’m wrong.
Arel is located in ActiveRecord gem. And has these kind of directory structure.
As I said, Arel is an AST manager. So there are classes that represents each statements. They are located in nodes
directory.
This contains classes for each table attributes with type such as STRING
, TIME
or BOOLEAN
, etc…
This contains AST nodes visitor and SQL engine specific codes. (for MySQL, PostgreSQL, etc…)
Table class has methods to access Arel::SelectManager
, Arel::Attribute
and Nodes::TableAlias
. And also has methods to construct query.(e.g. where
, join
, group
, order
, having
, etc...)
Attribute class represents attributes that belongs to the table.
Example
This seems to be a node forSELECT
statement. But it's different there is another node called Arel::Nodes::SelectStatement
which represents only SELECT
. Arel::SelectManager
has convenient methods to create AST tree.
There are another class like this.
A base class of each AST node classes.
Contain AST node visitors methods which used on creating SQL string. I’ll explain in later.
This allows to create a AST node for statement which not being declared in Arel by default. Here is a usage in Arel::FactoryMethods
.
I’ll follow what happens inside Arel when running this example code.
First, where
in select manager is defined in Arel::TreeManager
.
Simple enough. If the argument is Arel::TreeManager
then fetch AST from it. And put into @ctx.wheres
. Otherwise, put expr
directly into @ctx.wheres
. As Arel::TreeManager
is included in Arel::SelectManager
, this @ctx
is same as it on Arel::TreeManager
.
Table.engine
is initialized on ActiveRecord loaded. So this is a reference to ActiveRecord
to the module.
engine.connection
is defined in ActiveRecord::ConnectionHandling
. This is same method referenced with ActiveRecord::Base.connection
. This method returns a connection from connection pool.
Arel::Visitors::MySQL
is a subclass of Arel::Visitors::ToSql
. Major logics are written in Arel::Visitors::ToSql
. Arel::Visitors::MySQL
only has some engine specific code.
What happens inside when you call visit
?
Here is examples.
How about with the example code?
The @ast
has following structure.
Also @wheres
of the first @cores
looks like this.
We know that o
is an AST node of Arel::Nodes::SelectStatement
in this case. And collector
is Arel::Collectors::SQLString
.
Nothing happens on if o.with
block because it's empty.
I think I’ve got a feeling of how Arel working. So I’m gonna finish this article.
Thanks for reading!!
Build crazy queries with ActiveRecord and Arel
How does an enterprise get the most from their digital platform provider? Understanding how to customise and build a unified platform from different SaaS platforms is key.