marty 2.5.9 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/db/migrate/501_create_dg_plpgsql_v1_fns.rb +22 -0
- data/db/sql/lookup_grid_distinct_v1.sql +175 -0
- data/db/sql/query_grid_dir_v1.sql +100 -0
- data/lib/marty/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5793ffa9b322a289ab5cf900d733f296127f4840586baf8a95afe8793e9752cd
|
4
|
+
data.tar.gz: 6e1e78d9cbb3472ac5ed1f99a5592cc1718ab706eb1d878265a5682408d9b130
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e47115835ddf8cff33b27b6582f73cd77f5e802099c776981aa47311bae1f11047bbba797fe5def8c8188c5ae10de6e213dff1fe37dd51c974e1d326a2c22dc
|
7
|
+
data.tar.gz: 731b6b6799978cbd72416461ca55c1243eac694b324b8df497a5193d2416569b901c610d862e84a19d58810031c38d4b22d2206280bf9ceaa2ad917b7365ab65
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class CreateDgPlpgsqlV1Fns < ActiveRecord::Migration[4.2]
|
2
|
+
def up
|
3
|
+
marty_path = Gem.loaded_specs["marty"].full_gem_path
|
4
|
+
Dir.glob("#{marty_path}/db/sql/*_v1.sql") do |f|
|
5
|
+
connection.execute(File.read(f))
|
6
|
+
end
|
7
|
+
|
8
|
+
connection.execute('DROP FUNCTION IF EXISTS errinfo(err jsonb);')
|
9
|
+
end
|
10
|
+
|
11
|
+
def down
|
12
|
+
connection.execute <<-SQL
|
13
|
+
-- required to utilize plv8 extension
|
14
|
+
CREATE EXTENSION IF NOT EXISTS plv8;
|
15
|
+
SQL
|
16
|
+
|
17
|
+
marty_path = Gem.loaded_specs["marty"].full_gem_path
|
18
|
+
Dir.glob("#{marty_path}/db/js/*_v1.js") do |f|
|
19
|
+
connection.execute(Marty::Migrations.get_plv8_migration(f))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
CREATE OR REPLACE FUNCTION public.lookup_grid_distinct(h jsonb, row_info jsonb, return_grid_data boolean DEFAULT false, dis boolean DEFAULT false) RETURNS jsonb
|
2
|
+
LANGUAGE plpgsql
|
3
|
+
AS $_$
|
4
|
+
|
5
|
+
-- Finds a data grid metadata, calculates the SQL query for it's vertical and horizontal attributes
|
6
|
+
-- Fetches vertical and horizontal indexes and uses them to fetch value from data grid data
|
7
|
+
|
8
|
+
DECLARE
|
9
|
+
directions TEXT[] = ARRAY['h', 'v'];
|
10
|
+
direction TEXT;
|
11
|
+
|
12
|
+
data_grid_info JSONB;
|
13
|
+
data_grid_metadata JSONB;
|
14
|
+
data_grid_lenient BOOLEAN;
|
15
|
+
data_grid_data JSONB;
|
16
|
+
data_grid_name TEXT;
|
17
|
+
data_grid_group_id TEXT;
|
18
|
+
data_grid_metadata_h JSONB[];
|
19
|
+
data_grid_metadata_v JSONB[];
|
20
|
+
data_grid_metadata_current JSONB[];
|
21
|
+
|
22
|
+
horizontal_indexes JSONB = '[]'::JSONB;
|
23
|
+
horizontal_index INTEGER;
|
24
|
+
|
25
|
+
vertical_indexes JSONB = '[]'::JSONB;
|
26
|
+
vertical_index INTEGER;
|
27
|
+
|
28
|
+
query_dir_result JSONB;
|
29
|
+
query_index_result JSONB = '[]'::JSONB;
|
30
|
+
metadata_record JSONB;
|
31
|
+
|
32
|
+
all_results JSONB[];
|
33
|
+
sql_scripts_arr text[];
|
34
|
+
|
35
|
+
result JSONB;
|
36
|
+
return_json JSONB;
|
37
|
+
|
38
|
+
error_extra JSONB;
|
39
|
+
|
40
|
+
target RECORD;
|
41
|
+
BEGIN
|
42
|
+
EXECUTE 'SELECT metadata, lenient, name, data, group_id FROM marty_data_grids WHERE id = $1::INTEGER'
|
43
|
+
INTO data_grid_metadata, data_grid_lenient, data_grid_name, data_grid_data, data_grid_group_id
|
44
|
+
USING row_info ->> 'id';
|
45
|
+
|
46
|
+
|
47
|
+
data_grid_metadata := COALESCE(data_grid_metadata, '[]'::JSONB);
|
48
|
+
|
49
|
+
FOR i IN 0 .. (jsonb_array_length(data_grid_metadata) - 1) LOOP
|
50
|
+
metadata_record := data_grid_metadata -> i;
|
51
|
+
IF (metadata_record ->> 'dir') = 'h' THEN
|
52
|
+
data_grid_metadata_h := data_grid_metadata_h || metadata_record;
|
53
|
+
ELSIF (metadata_record ->> 'dir') = 'v' THEN
|
54
|
+
data_grid_metadata_v := data_grid_metadata_v || metadata_record;
|
55
|
+
END IF;
|
56
|
+
END LOOP;
|
57
|
+
|
58
|
+
FOREACH direction IN ARRAY directions LOOP
|
59
|
+
|
60
|
+
IF direction = 'h' THEN
|
61
|
+
data_grid_metadata_current := data_grid_metadata_h;
|
62
|
+
ELSE
|
63
|
+
data_grid_metadata_current := data_grid_metadata_v;
|
64
|
+
END IF;
|
65
|
+
|
66
|
+
|
67
|
+
IF COALESCE(array_length(data_grid_metadata_current, 1), 0) = 0 THEN
|
68
|
+
IF direction = 'h' THEN
|
69
|
+
horizontal_indexes := '[0]'::JSONB;
|
70
|
+
ELSE
|
71
|
+
vertical_indexes := '[0]'::JSONB;
|
72
|
+
END IF;
|
73
|
+
CONTINUE;
|
74
|
+
END IF;
|
75
|
+
|
76
|
+
-- fetch the resulting SQL query and it's arguments for current direction
|
77
|
+
EXECUTE 'SELECT public.query_grid_dir($1, $2, $3)'
|
78
|
+
INTO query_dir_result
|
79
|
+
USING h, data_grid_metadata_current, row_info;
|
80
|
+
|
81
|
+
IF query_dir_result ->> 0 IS NULL THEN
|
82
|
+
CONTINUE;
|
83
|
+
END IF;
|
84
|
+
|
85
|
+
sql_scripts_arr := sql_scripts_arr || (query_dir_result ->> 0);
|
86
|
+
|
87
|
+
query_index_result := '[]'::JSONB;
|
88
|
+
|
89
|
+
-- execute the SQL query that has been received before and
|
90
|
+
-- add it's (possibly multiple) results to query_index_result variable
|
91
|
+
FOR target IN EXECUTE query_dir_result ->> 0 USING query_dir_result -> 1 LOOP
|
92
|
+
query_index_result := query_index_result || to_jsonb(target.index);
|
93
|
+
END LOOP;
|
94
|
+
|
95
|
+
all_results := all_results || query_index_result;
|
96
|
+
query_index_result := '[]'::JSONB || query_index_result; -- Use empty JSONB array in case of NULL results
|
97
|
+
|
98
|
+
IF direction = 'h' THEN
|
99
|
+
horizontal_indexes := query_index_result;
|
100
|
+
ELSE
|
101
|
+
vertical_indexes := query_index_result;
|
102
|
+
END IF;
|
103
|
+
|
104
|
+
|
105
|
+
IF dis AND jsonb_array_length(query_index_result) > 1 THEN
|
106
|
+
RAISE EXCEPTION 'matches > 1';
|
107
|
+
END IF;
|
108
|
+
|
109
|
+
END LOOP;
|
110
|
+
|
111
|
+
vertical_indexes := COALESCE(vertical_indexes, '[]'::JSONB);
|
112
|
+
horizontal_indexes := COALESCE(horizontal_indexes, '[]'::JSONB);
|
113
|
+
|
114
|
+
IF ((jsonb_array_length(vertical_indexes)) = 0
|
115
|
+
OR (jsonb_array_length(horizontal_indexes)) = 0)
|
116
|
+
AND NOT data_grid_lenient
|
117
|
+
AND NOT return_grid_data THEN
|
118
|
+
|
119
|
+
RAISE EXCEPTION 'Data Grid lookup failed';
|
120
|
+
END IF;
|
121
|
+
|
122
|
+
-- Get the smalles vertical index
|
123
|
+
IF jsonb_array_length(vertical_indexes) > 0 THEN
|
124
|
+
FOR i IN 0 .. (jsonb_array_length(vertical_indexes) - 1) LOOP
|
125
|
+
vertical_index := LEAST(vertical_index, (vertical_indexes ->> i)::INTEGER);
|
126
|
+
END LOOP;
|
127
|
+
END IF;
|
128
|
+
|
129
|
+
-- Get the smalles horizontal index
|
130
|
+
IF jsonb_array_length(horizontal_indexes) > 0 THEN
|
131
|
+
FOR i IN 0 .. (jsonb_array_length(vertical_indexes) - 1) LOOP
|
132
|
+
horizontal_index := LEAST(horizontal_index, (horizontal_indexes ->> i)::INTEGER);
|
133
|
+
END LOOP;
|
134
|
+
END IF;
|
135
|
+
|
136
|
+
IF vertical_index IS NOT NULL and horizontal_index IS NOT NULL THEN
|
137
|
+
result := data_grid_data -> vertical_index -> horizontal_index;
|
138
|
+
END IF;
|
139
|
+
|
140
|
+
IF NOT return_grid_data THEN
|
141
|
+
data_grid_data := NULL;
|
142
|
+
data_grid_metadata := NULL;
|
143
|
+
END IF;
|
144
|
+
|
145
|
+
return_json := jsonb_build_object(
|
146
|
+
'result', result,
|
147
|
+
'name', data_grid_name,
|
148
|
+
'data', data_grid_data,
|
149
|
+
'metadata', data_grid_metadata
|
150
|
+
);
|
151
|
+
|
152
|
+
RETURN return_json;
|
153
|
+
|
154
|
+
EXCEPTION WHEN OTHERS THEN
|
155
|
+
error_extra := jsonb_build_object(
|
156
|
+
'error', SQLERRM,
|
157
|
+
'sql', sql_scripts_arr,
|
158
|
+
'results', all_results,
|
159
|
+
'params', h,
|
160
|
+
'dg', jsonb_build_object(
|
161
|
+
'name', data_grid_name,
|
162
|
+
'data', data_grid_data,
|
163
|
+
'metadata', data_grid_metadata,
|
164
|
+
'group_id', data_grid_group_id,
|
165
|
+
'lenient', data_grid_lenient
|
166
|
+
)
|
167
|
+
);
|
168
|
+
|
169
|
+
RETURN jsonb_build_object(
|
170
|
+
'error', SQLERRM,
|
171
|
+
'error_extra', error_extra
|
172
|
+
);
|
173
|
+
END
|
174
|
+
|
175
|
+
$_$;
|
@@ -0,0 +1,100 @@
|
|
1
|
+
CREATE OR REPLACE FUNCTION public.query_grid_dir(h jsonb, infos jsonb[], row_info jsonb) returns jsonb
|
2
|
+
LANGUAGE plpgsql
|
3
|
+
AS $$
|
4
|
+
|
5
|
+
-- Iterates through infos and and builds a one big SQL query
|
6
|
+
-- with one SELECT per info and INTERSECT between those SELECTs
|
7
|
+
-- in order to find the cells that multiple vertical or horizontal headers are pointing to.
|
8
|
+
-- Return JSONB array with resulting SQL query and JSONB array of it's arguments.
|
9
|
+
-- Each of the argument is references via it's index in JSONB array. Example: ($1 ->> 0)
|
10
|
+
|
11
|
+
DECLARE
|
12
|
+
args text[];
|
13
|
+
sqlidx integer = 0;
|
14
|
+
i integer;
|
15
|
+
|
16
|
+
attr_type text;
|
17
|
+
attr_name text;
|
18
|
+
attr_value text;
|
19
|
+
h_key_exists boolean;
|
20
|
+
|
21
|
+
table_name text;
|
22
|
+
sql_script text;
|
23
|
+
sql_scripts_arr text[];
|
24
|
+
sql_scripts_arr_intersect text;
|
25
|
+
sql_filter text;
|
26
|
+
|
27
|
+
BEGIN
|
28
|
+
FOR i IN 1 .. COALESCE(array_upper(infos, 1), 0)
|
29
|
+
LOOP
|
30
|
+
attr_type := infos[i] ->> 'type';
|
31
|
+
attr_name := infos[i] ->> 'attr';
|
32
|
+
attr_value := h ->> attr_name;
|
33
|
+
h_key_exists := h ? attr_name;
|
34
|
+
|
35
|
+
IF NOT h_key_exists THEN
|
36
|
+
CONTINUE;
|
37
|
+
END IF;
|
38
|
+
|
39
|
+
CASE attr_type
|
40
|
+
WHEN 'boolean' THEN
|
41
|
+
table_name := 'marty_grid_index_' || attr_type || 's';
|
42
|
+
WHEN 'numrange' THEN
|
43
|
+
table_name := 'marty_grid_index_' || attr_type || 's';
|
44
|
+
WHEN 'int4range' THEN
|
45
|
+
table_name := 'marty_grid_index_' || attr_type || 's';
|
46
|
+
WHEN 'integer' THEN
|
47
|
+
table_name := 'marty_grid_index_' || attr_type || 's';
|
48
|
+
ELSE
|
49
|
+
table_name := 'marty_grid_index_strings';
|
50
|
+
END CASE;
|
51
|
+
|
52
|
+
sql_script = 'SELECT DISTINCT index from ' || table_name ||
|
53
|
+
-- Convertion to FLOAT is neeed to make numbers like 2005.0 work
|
54
|
+
' WHERE data_grid_id = ($1 ->> ' || sqlidx || ')::FLOAT::INTEGER' ||
|
55
|
+
' AND created_dt = ($1 ->> ' || (sqlidx + 1) || ')::TIMESTAMP' ||
|
56
|
+
' AND attr = $1 ->> ' || (sqlidx + 2) || ' ';
|
57
|
+
|
58
|
+
sqlidx := sqlidx + 3;
|
59
|
+
|
60
|
+
args := args || (row_info ->> 'group_id');
|
61
|
+
args := args || (row_info ->> 'created_dt');
|
62
|
+
args := args || attr_name;
|
63
|
+
|
64
|
+
IF attr_value IS NULL THEN
|
65
|
+
sql_filter := '';
|
66
|
+
ELSE
|
67
|
+
CASE attr_type
|
68
|
+
WHEN 'boolean' THEN
|
69
|
+
sql_filter := 'key = ($1 ->> ' || sqlidx || ')::BOOLEAN OR ';
|
70
|
+
WHEN 'numrange' THEN
|
71
|
+
sql_filter := 'key @> ($1 ->> ' || sqlidx || ')::NUMERIC OR ';
|
72
|
+
WHEN 'int4range' THEN
|
73
|
+
-- Convertion to FLOAT is neeed to make numbers like 2005.0 work
|
74
|
+
sql_filter := 'key @> ($1 ->> ' || sqlidx || ')::FLOAT::INTEGER OR ';
|
75
|
+
WHEN 'integer' THEN
|
76
|
+
-- Convertion to FLOAT is neeed to make numbers like 2005.0 work
|
77
|
+
sql_filter := 'key @> ARRAY[($1 ->> ' || sqlidx || ')::FLOAT::INTEGER] OR ';
|
78
|
+
ELSE
|
79
|
+
sql_filter := 'key @> ARRAY[($1 ->> ' || sqlidx || ')::TEXT] OR ';
|
80
|
+
END CASE;
|
81
|
+
|
82
|
+
sqlidx := sqlidx + 1;
|
83
|
+
args := args || attr_value;
|
84
|
+
END IF;
|
85
|
+
|
86
|
+
sql_script := sql_script || ' AND (' || sql_filter || 'key is NULL) ';
|
87
|
+
|
88
|
+
sql_scripts_arr := sql_scripts_arr || sql_script;
|
89
|
+
END LOOP;
|
90
|
+
|
91
|
+
IF array_length(sql_scripts_arr, 1) = 0 THEN
|
92
|
+
RETURN NULL;
|
93
|
+
END IF;
|
94
|
+
|
95
|
+
sql_scripts_arr_intersect := array_to_string(sql_scripts_arr, ' INTERSECT ');
|
96
|
+
|
97
|
+
RETURN json_build_array(sql_scripts_arr_intersect, args);
|
98
|
+
END;
|
99
|
+
|
100
|
+
$$;
|
data/lib/marty/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arman Bostani
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2019-03-
|
17
|
+
date: 2019-03-25 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: pg
|
@@ -379,7 +379,10 @@ files:
|
|
379
379
|
- db/migrate/410_jsonb_promise_result.rb
|
380
380
|
- db/migrate/411_create_vw_promises.rb
|
381
381
|
- db/migrate/500_add_api_class_to_marty_api_config.rb
|
382
|
+
- db/migrate/501_create_dg_plpgsql_v1_fns.rb
|
382
383
|
- db/seeds.rb
|
384
|
+
- db/sql/lookup_grid_distinct_v1.sql
|
385
|
+
- db/sql/query_grid_dir_v1.sql
|
383
386
|
- delorean/blame_report.dl
|
384
387
|
- delorean/diagnostics.dl
|
385
388
|
- delorean/marty_fields.dl
|