arel_toolkit 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/develop.yml +86 -0
- data/.github/workflows/master.yml +67 -0
- data/.gitignore +4 -0
- data/CHANGELOG.md +35 -3
- data/Gemfile.lock +22 -15
- data/Guardfile +4 -0
- data/README.md +11 -8
- data/Rakefile +11 -1
- data/arel_toolkit.gemspec +4 -1
- data/ext/pg_result_init/extconf.rb +52 -0
- data/ext/pg_result_init/pg_result_init.c +138 -0
- data/ext/pg_result_init/pg_result_init.h +6 -0
- data/gemfiles/arel_gems.gemfile.lock +7 -0
- data/gemfiles/default.gemfile.lock +7 -0
- data/lib/arel/enhance.rb +1 -0
- data/lib/arel/enhance/context_enhancer/arel_table.rb +18 -1
- data/lib/arel/enhance/node.rb +25 -6
- data/lib/arel/enhance/query.rb +2 -0
- data/lib/arel/enhance/query_methods.rb +23 -0
- data/lib/arel/enhance/visitor.rb +4 -2
- data/lib/arel/extensions.rb +7 -2
- data/lib/arel/extensions/active_model_attribute_with_cast_value.rb +22 -0
- data/lib/arel/extensions/active_record_relation_query_attribute.rb +22 -0
- data/lib/arel/extensions/active_record_type_caster_connection.rb +7 -0
- data/lib/arel/extensions/attributes_attribute.rb +47 -0
- data/lib/arel/extensions/bind_param.rb +15 -0
- data/lib/arel/extensions/coalesce.rb +17 -3
- data/lib/arel/extensions/exists.rb +59 -0
- data/lib/arel/extensions/function.rb +2 -1
- data/lib/arel/extensions/greatest.rb +17 -3
- data/lib/arel/extensions/insert_statement.rb +2 -2
- data/lib/arel/extensions/least.rb +17 -3
- data/lib/arel/extensions/node.rb +10 -0
- data/lib/arel/extensions/range_function.rb +10 -2
- data/lib/arel/extensions/select_core.rb +1 -0
- data/lib/arel/extensions/tree_manager.rb +5 -0
- data/lib/arel/middleware.rb +5 -1
- data/lib/arel/middleware/active_record_extension.rb +13 -0
- data/lib/arel/middleware/chain.rb +76 -21
- data/lib/arel/middleware/database_executor.rb +68 -0
- data/lib/arel/middleware/postgresql_adapter.rb +41 -5
- data/lib/arel/middleware/railtie.rb +6 -2
- data/lib/arel/middleware/result.rb +170 -0
- data/lib/arel/middleware/to_sql_executor.rb +15 -0
- data/lib/arel/middleware/to_sql_middleware.rb +33 -0
- data/lib/arel/sql_to_arel/pg_query_visitor.rb +34 -33
- data/lib/arel/sql_to_arel/result.rb +19 -2
- data/lib/arel/transformer.rb +2 -1
- data/lib/arel/transformer/prefix_schema_name.rb +183 -0
- data/lib/arel/transformer/remove_active_record_info.rb +2 -4
- data/lib/arel/transformer/replace_table_with_subquery.rb +31 -0
- data/lib/arel_toolkit.rb +6 -1
- data/lib/arel_toolkit/version.rb +1 -1
- metadata +55 -10
- data/.travis.yml +0 -34
- data/lib/arel/extensions/generate_series.rb +0 -9
- data/lib/arel/extensions/rank.rb +0 -9
- data/lib/arel/transformer/add_schema_to_table.rb +0 -26
@@ -0,0 +1,68 @@
|
|
1
|
+
module Arel
|
2
|
+
module Middleware
|
3
|
+
class DatabaseExecutor
|
4
|
+
attr_reader :middleware
|
5
|
+
|
6
|
+
attr_accessor :index
|
7
|
+
attr_reader :context
|
8
|
+
attr_reader :final_block
|
9
|
+
|
10
|
+
def initialize(middleware)
|
11
|
+
@middleware = middleware
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(enhanced_arel, context, final_block)
|
15
|
+
@index = 0
|
16
|
+
@context = context
|
17
|
+
@final_block = final_block
|
18
|
+
|
19
|
+
result = call(enhanced_arel)
|
20
|
+
check_return_type result
|
21
|
+
result
|
22
|
+
ensure
|
23
|
+
@index = 0
|
24
|
+
@context = nil
|
25
|
+
@final_block = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(next_arel)
|
29
|
+
check_argument_type next_arel
|
30
|
+
|
31
|
+
current_middleware = middleware[index]
|
32
|
+
|
33
|
+
return execute_sql(next_arel) if current_middleware.nil?
|
34
|
+
|
35
|
+
self.index += 1
|
36
|
+
|
37
|
+
case current_middleware.method(:call).arity
|
38
|
+
when 2
|
39
|
+
current_middleware.call(next_arel, self)
|
40
|
+
else
|
41
|
+
current_middleware.call(next_arel, self, context.dup)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def execute_sql(next_arel)
|
48
|
+
sql, binds = next_arel.to_sql_and_binds
|
49
|
+
sql_result = final_block.call(sql, binds)
|
50
|
+
check_return_type sql_result
|
51
|
+
sql_result
|
52
|
+
end
|
53
|
+
|
54
|
+
def check_argument_type(next_arel)
|
55
|
+
return if next_arel.is_a?(Arel::Enhance::Node)
|
56
|
+
|
57
|
+
raise "Only `Arel::Enhance::Node` is valid for middleware, passed `#{next_arel.class}`"
|
58
|
+
end
|
59
|
+
|
60
|
+
def check_return_type(return_object)
|
61
|
+
return if return_object.is_a?(Arel::Middleware::Result)
|
62
|
+
|
63
|
+
raise 'Object returned from middleware needs to be wrapped in `Arel::Middleware::Result`' \
|
64
|
+
" for object `#{return_object}`"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -8,18 +8,54 @@ module Arel
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def execute(sql, name = nil)
|
11
|
-
sql = Arel::Middleware.current_chain.execute(sql)
|
12
11
|
super(sql, name)
|
13
12
|
end
|
14
13
|
|
14
|
+
alias parent_execute execute
|
15
|
+
|
16
|
+
# rubocop:disable Lint/DuplicateMethods
|
17
|
+
def execute(sql, name = nil)
|
18
|
+
Arel::Middleware.current_chain.execute(sql) do |processed_sql|
|
19
|
+
Arel::Middleware::Result.create(
|
20
|
+
data: parent_execute(processed_sql, name),
|
21
|
+
from: Arel::Middleware::PGResult,
|
22
|
+
to: Arel::Middleware::PGResult,
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
# rubocop:enable Lint/DuplicateMethods
|
27
|
+
|
28
|
+
def query(sql, name = nil)
|
29
|
+
Arel::Middleware.current_chain.execute(sql) do |processed_sql|
|
30
|
+
# NOTE: we're not calling `super` here, but execute.
|
31
|
+
# The `query` super does not return the columns, like the other methods.
|
32
|
+
# As we want the result objects to be the same, we call execute instead.
|
33
|
+
Arel::Middleware::Result.create(
|
34
|
+
data: parent_execute(processed_sql, name),
|
35
|
+
from: Arel::Middleware::PGResult,
|
36
|
+
to: Arel::Middleware::ArrayResult,
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
15
41
|
def exec_no_cache(sql, name, binds)
|
16
|
-
|
17
|
-
|
42
|
+
Arel::Middleware.current_chain.execute(sql, binds) do |processed_sql, processed_binds|
|
43
|
+
Arel::Middleware::Result.create(
|
44
|
+
data: super(processed_sql, name, processed_binds),
|
45
|
+
from: Arel::Middleware::PGResult,
|
46
|
+
to: Arel::Middleware::PGResult,
|
47
|
+
)
|
48
|
+
end
|
18
49
|
end
|
19
50
|
|
20
51
|
def exec_cache(sql, name, binds)
|
21
|
-
|
22
|
-
|
52
|
+
Arel::Middleware.current_chain.execute(sql, binds) do |processed_sql, processed_binds|
|
53
|
+
Arel::Middleware::Result.create(
|
54
|
+
data: super(processed_sql, name, processed_binds),
|
55
|
+
from: Arel::Middleware::PGResult,
|
56
|
+
to: Arel::Middleware::PGResult,
|
57
|
+
)
|
58
|
+
end
|
23
59
|
end
|
24
60
|
end
|
25
61
|
end
|
@@ -4,17 +4,21 @@ module Arel
|
|
4
4
|
class Railtie < Rails::Railtie
|
5
5
|
initializer 'arel.middleware.insert' do
|
6
6
|
ActiveSupport.on_load :active_record do
|
7
|
-
Arel::Middleware::Railtie.
|
7
|
+
Arel::Middleware::Railtie.insert
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
class Railtie
|
14
|
-
def self.
|
14
|
+
def self.insert
|
15
15
|
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(
|
16
16
|
Arel::Middleware::PostgreSQLAdapter,
|
17
17
|
)
|
18
|
+
|
19
|
+
ActiveRecord::Base.singleton_class.prepend(
|
20
|
+
Arel::Middleware::ActiveRecordExtension,
|
21
|
+
)
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module Arel
|
2
|
+
module Middleware
|
3
|
+
class Column
|
4
|
+
attr_reader :name
|
5
|
+
attr_reader :metadata
|
6
|
+
|
7
|
+
def initialize(name, metadata)
|
8
|
+
@name = name
|
9
|
+
@metadata = metadata
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Class is very similar to ActiveRecord::Result
|
14
|
+
# activerecord/lib/active_record/result.rb
|
15
|
+
class Result
|
16
|
+
attr_reader :original_data
|
17
|
+
|
18
|
+
def self.create(from:, to:, data:)
|
19
|
+
Result.new from, to, data
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(from_caster, to_caster, original_data)
|
23
|
+
@from_caster = from_caster
|
24
|
+
@to_caster = to_caster
|
25
|
+
@original_data = original_data
|
26
|
+
@modified = false
|
27
|
+
end
|
28
|
+
|
29
|
+
def columns
|
30
|
+
@columns ||= column_objects.map(&:name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def column_objects
|
34
|
+
@column_objects ||= from_caster.column_objects(original_data)
|
35
|
+
end
|
36
|
+
|
37
|
+
def rows
|
38
|
+
@rows ||= from_caster.rows(original_data)
|
39
|
+
end
|
40
|
+
|
41
|
+
def remove_column(column_name)
|
42
|
+
column_index = columns.index(column_name)
|
43
|
+
raise "Unknown column `#{column_name}`. Existing columns: `#{columns}`" if column_index.nil?
|
44
|
+
|
45
|
+
@hash_rows = nil
|
46
|
+
@columns = nil
|
47
|
+
@modified = true
|
48
|
+
|
49
|
+
column_objects.delete_at(column_index)
|
50
|
+
deleted_rows = []
|
51
|
+
|
52
|
+
rows.map! do |row|
|
53
|
+
deleted_rows << row.delete_at(column_index)
|
54
|
+
row
|
55
|
+
end
|
56
|
+
|
57
|
+
deleted_rows
|
58
|
+
end
|
59
|
+
|
60
|
+
def hash_rows
|
61
|
+
@hash_rows ||=
|
62
|
+
begin
|
63
|
+
rows.map do |row|
|
64
|
+
hash = {}
|
65
|
+
|
66
|
+
index = 0
|
67
|
+
length = columns.length
|
68
|
+
|
69
|
+
while index < length
|
70
|
+
hash[columns[index]] = row[index]
|
71
|
+
index += 1
|
72
|
+
end
|
73
|
+
|
74
|
+
hash
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_casted_result
|
80
|
+
to_caster.cast_to(self)
|
81
|
+
end
|
82
|
+
|
83
|
+
def modified?
|
84
|
+
@modified
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
attr_reader :to_caster, :from_caster
|
90
|
+
end
|
91
|
+
|
92
|
+
class PGResult
|
93
|
+
class << self
|
94
|
+
def column_objects(pg_result)
|
95
|
+
pg_result.fields.each_with_index.map do |field, index|
|
96
|
+
Column.new(
|
97
|
+
field,
|
98
|
+
tableid: pg_result.ftable(index),
|
99
|
+
columnid: pg_result.ftablecol(index),
|
100
|
+
format: pg_result.fformat(index),
|
101
|
+
typid: pg_result.ftype(index),
|
102
|
+
typlen: pg_result.fsize(index),
|
103
|
+
atttypmod: pg_result.fmod(index),
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def rows(data)
|
109
|
+
data.values
|
110
|
+
end
|
111
|
+
|
112
|
+
def cast_to(result)
|
113
|
+
return result.original_data unless result.modified?
|
114
|
+
|
115
|
+
pg_columns = result_to_columns(result)
|
116
|
+
conn = ActiveRecord::Base.connection.raw_connection
|
117
|
+
new_result = PgResultInit.create(conn, result.original_data, pg_columns, result.rows)
|
118
|
+
result.original_data.clear
|
119
|
+
new_result
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def result_to_columns(result)
|
125
|
+
result.column_objects.map do |column|
|
126
|
+
{
|
127
|
+
name: column.name,
|
128
|
+
tableid: column.metadata.fetch(:tableid, 0),
|
129
|
+
columnid: column.metadata.fetch(:columnid, 0),
|
130
|
+
format: column.metadata.fetch(:format, 0),
|
131
|
+
typid: column.metadata.fetch(:typid),
|
132
|
+
typlen: column.metadata.fetch(:typlen),
|
133
|
+
atttypmod: column.metadata.fetch(:atttypmod, -1),
|
134
|
+
}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class EmptyPGResult < PGResult
|
141
|
+
class << self
|
142
|
+
def cast_to(_result)
|
143
|
+
ActiveRecord::Base.connection.raw_connection.make_empty_pgresult(2)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class ArrayResult
|
149
|
+
def self.cast_to(result)
|
150
|
+
result.rows
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
class StringResult
|
155
|
+
class << self
|
156
|
+
def column_objects(_string)
|
157
|
+
[]
|
158
|
+
end
|
159
|
+
|
160
|
+
def rows(_string)
|
161
|
+
[]
|
162
|
+
end
|
163
|
+
|
164
|
+
def cast_to(result)
|
165
|
+
result.original_data
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Arel
|
2
|
+
module Middleware
|
3
|
+
class ToSqlExecutor < DatabaseExecutor
|
4
|
+
private
|
5
|
+
|
6
|
+
def execute_sql(next_arel)
|
7
|
+
Arel::Middleware::Result.create(
|
8
|
+
data: next_arel.to_sql,
|
9
|
+
from: Arel::Middleware::StringResult,
|
10
|
+
to: Arel::Middleware::EmptyPGResult,
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Arel
|
2
|
+
module Middleware
|
3
|
+
class ToSqlMiddleware
|
4
|
+
attr_reader :sql, :type, :query_class
|
5
|
+
|
6
|
+
def initialize(type)
|
7
|
+
@sql = []
|
8
|
+
@type = type
|
9
|
+
@query_class = class_from_type
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(next_arel, next_middleware)
|
13
|
+
sql << next_arel.to_sql unless next_arel.query(class: query_class).empty?
|
14
|
+
next_middleware.call(next_arel)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def class_from_type
|
20
|
+
case type
|
21
|
+
when :insert
|
22
|
+
Arel::Nodes::InsertStatement
|
23
|
+
when :select
|
24
|
+
Arel::Nodes::SelectStatement
|
25
|
+
when :update
|
26
|
+
Arel::Nodes::UpdateStatement
|
27
|
+
when :delete
|
28
|
+
Arel::Nodes::DeleteStatement
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -26,6 +26,9 @@ module Arel
|
|
26
26
|
@sql = sql
|
27
27
|
|
28
28
|
Result.new visit(object, :top)
|
29
|
+
rescue ::PgQuery::ParseError => e
|
30
|
+
new_error = ::PgQuery::ParseError.new(e.message, __FILE__, __LINE__, -1)
|
31
|
+
raise new_error, e.message, e.backtrace
|
29
32
|
rescue ::StandardError => e
|
30
33
|
raise e.class, e.message, e.backtrace if e.is_a?(Arel::SqlToArel::Error)
|
31
34
|
|
@@ -192,7 +195,7 @@ module Arel
|
|
192
195
|
end
|
193
196
|
|
194
197
|
def visit_Alias(aliasname:)
|
195
|
-
aliasname
|
198
|
+
Arel.sql visit_String(nil, str: aliasname)
|
196
199
|
end
|
197
200
|
|
198
201
|
def visit_BitString(str:)
|
@@ -278,22 +281,20 @@ module Arel
|
|
278
281
|
end
|
279
282
|
|
280
283
|
def visit_ColumnRef(fields:)
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
284
|
+
fields = fields.reverse
|
285
|
+
column = visit(fields[0], :operator)
|
286
|
+
table = visit(fields[1], :operator) if fields[1]
|
287
|
+
schema_name = visit(fields[2], :operator) if fields[2]
|
288
|
+
database = visit(fields[3], :operator) if fields[3]
|
285
289
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
+
table = Arel::Table.new(table) if table
|
291
|
+
attribute = Arel::Attribute.new(table, column)
|
292
|
+
attribute.schema_name = schema_name
|
293
|
+
attribute.database = database
|
290
294
|
|
291
|
-
|
292
|
-
table[column_reference]
|
295
|
+
return attribute if table
|
293
296
|
|
294
|
-
|
295
|
-
raise 'Can\'t deal with column refs that have more than 2 fields'
|
296
|
-
end
|
297
|
+
Arel::Nodes::UnqualifiedColumn.new Arel::Attribute.new(nil, column)
|
297
298
|
end
|
298
299
|
|
299
300
|
def visit_CommonTableExpr(ctename:, ctequery:)
|
@@ -364,15 +365,9 @@ module Arel
|
|
364
365
|
when ['sum']
|
365
366
|
Arel::Nodes::Sum.new args
|
366
367
|
|
367
|
-
when ['rank']
|
368
|
-
Arel::Nodes::Rank.new args
|
369
|
-
|
370
368
|
when ['count']
|
371
369
|
Arel::Nodes::Count.new args
|
372
370
|
|
373
|
-
when ['generate_series']
|
374
|
-
Arel::Nodes::GenerateSeries.new args
|
375
|
-
|
376
371
|
when ['max']
|
377
372
|
Arel::Nodes::Max.new args
|
378
373
|
|
@@ -429,10 +424,6 @@ module Arel
|
|
429
424
|
else
|
430
425
|
case function_names.length
|
431
426
|
when 2
|
432
|
-
if function_names.first == PG_CATALOG
|
433
|
-
boom "Missing postgres function `#{function_names.last}`"
|
434
|
-
end
|
435
|
-
|
436
427
|
func = Arel::Nodes::NamedFunction.new(function_names.last, args)
|
437
428
|
func.schema_name = function_names.first
|
438
429
|
func
|
@@ -602,15 +593,19 @@ module Arel
|
|
602
593
|
conflict
|
603
594
|
end
|
604
595
|
|
605
|
-
def visit_ParamRef(number:)
|
596
|
+
def visit_ParamRef(number: nil)
|
606
597
|
value = (binds[number - 1] unless binds.empty?)
|
607
598
|
|
608
599
|
Arel::Nodes::BindParam.new(value)
|
609
600
|
end
|
610
601
|
|
611
|
-
def visit_RangeFunction(
|
612
|
-
|
613
|
-
|
602
|
+
def visit_RangeFunction(
|
603
|
+
is_rowsfrom: nil,
|
604
|
+
functions:,
|
605
|
+
lateral: false,
|
606
|
+
ordinality: false,
|
607
|
+
aliaz: nil
|
608
|
+
)
|
614
609
|
functions = functions.map do |function_array|
|
615
610
|
function, empty_value = function_array
|
616
611
|
boom 'https://github.com/mvgijssel/arel_toolkit/issues/37' unless empty_value.nil?
|
@@ -618,15 +613,16 @@ module Arel
|
|
618
613
|
visit(function)
|
619
614
|
end
|
620
615
|
|
621
|
-
node = Arel::Nodes::RangeFunction.new functions
|
616
|
+
node = Arel::Nodes::RangeFunction.new functions, is_rowsfrom: is_rowsfrom
|
622
617
|
node = lateral ? Arel::Nodes::Lateral.new(node) : node
|
623
|
-
ordinality ? Arel::Nodes::WithOrdinality.new(node) : node
|
618
|
+
node = ordinality ? Arel::Nodes::WithOrdinality.new(node) : node
|
619
|
+
aliaz.nil? ? node : Arel::Nodes::As.new(node, visit(aliaz))
|
624
620
|
end
|
625
621
|
|
626
622
|
def visit_RangeSubselect(aliaz:, subquery:, lateral: false)
|
627
623
|
aliaz = visit(aliaz)
|
628
624
|
subquery = visit(subquery)
|
629
|
-
node = Arel::Nodes::
|
625
|
+
node = Arel::Nodes::As.new(Arel::Nodes::Grouping.new(subquery), aliaz)
|
630
626
|
lateral ? Arel::Nodes::Lateral.new(node) : node
|
631
627
|
end
|
632
628
|
|
@@ -650,7 +646,8 @@ module Arel
|
|
650
646
|
val = visit(val)
|
651
647
|
|
652
648
|
if name
|
653
|
-
|
649
|
+
aliaz = visit_Alias(aliasname: name)
|
650
|
+
Arel::Nodes::As.new(val, aliaz)
|
654
651
|
else
|
655
652
|
val
|
656
653
|
end
|
@@ -722,6 +719,7 @@ module Arel
|
|
722
719
|
select_core.havings = [visit(having_clause)] if having_clause
|
723
720
|
select_core.windows = visit(window_clause) if window_clause
|
724
721
|
select_core.into = visit(into_clause) if into_clause
|
722
|
+
select_core.top = ::Arel::Nodes::Top.new visit(limit_count) if limit_count
|
725
723
|
|
726
724
|
if distinct_clause == [nil]
|
727
725
|
select_core.set_quantifier = Arel::Nodes::Distinct.new
|
@@ -950,8 +948,11 @@ module Arel
|
|
950
948
|
start_offset: nil,
|
951
949
|
end_offset: nil
|
952
950
|
)
|
953
|
-
|
951
|
+
if name.present? && partition_clause.empty? && order_clause.empty?
|
952
|
+
return Arel::Nodes::SqlLiteral.new(name)
|
953
|
+
end
|
954
954
|
|
955
|
+
instance = name.nil? ? Arel::Nodes::Window.new : Arel::Nodes::NamedWindow.new(name)
|
955
956
|
instance.tap do |window|
|
956
957
|
window.orders = visit order_clause
|
957
958
|
window.partitions = visit partition_clause
|