From b4c3a0734c6ff11acf545f5ca6237e60adb9fd58 Mon Sep 17 00:00:00 2001 From: Kevin Jerinsky Date: Wed, 6 Mar 2024 12:53:25 -0500 Subject: [PATCH 1/2] optimize operations_for_operation_sets --- CHANGELOG.md | 3 ++ lib/policy_machine/version.rb | 2 +- .../active_record/postgresql.rb | 42 ++++++++++++------- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c15b91..a1865bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 4.1.2 +* Updated PostgreSQL `operations_for_operation_sets` with performance improvements + ## 4.1.1 * Updated PostgreSQL `operations_for_operation_sets` to guarantee disable mergejoin diff --git a/lib/policy_machine/version.rb b/lib/policy_machine/version.rb index fa8b480..069b094 100644 --- a/lib/policy_machine/version.rb +++ b/lib/policy_machine/version.rb @@ -1,3 +1,3 @@ class PolicyMachine - VERSION = "4.1.1" + VERSION = "4.1.2" end diff --git a/lib/policy_machine_storage_adapters/active_record/postgresql.rb b/lib/policy_machine_storage_adapters/active_record/postgresql.rb index 580a473..2093682 100644 --- a/lib/policy_machine_storage_adapters/active_record/postgresql.rb +++ b/lib/policy_machine_storage_adapters/active_record/postgresql.rb @@ -7,10 +7,21 @@ class PolicyElement # representing all operations contained by the given operation set ids # optionally can give a list of operation names to filter by def self.operations_for_operation_sets(operation_set_ids, operation_names = nil) + query_args = [operation_set_ids] + + operation_predicate = + if operation_names + query_args.append(operation_names) + 'unique_identifier IN (?)' + else + query_args.append(PolicyMachineStorageAdapter::ActiveRecord.class_for_type('operation').name) + '"type" = ?' + end + query = <<~SQL SET LOCAL enable_mergejoin TO FALSE; - WITH RECURSIVE accessible_operations AS ( + WITH RECURSIVE accessible_operations AS MATERIALIZED ( ( SELECT child_id, @@ -28,23 +39,24 @@ def self.operations_for_operation_sets(operation_set_ids, operation_names = nil) FROM assignments JOIN accessible_operations ON accessible_operations.child_id = assignments.parent_id ) + ), operations AS MATERIALIZED ( + SELECT + id, + unique_identifier + FROM policy_elements + WHERE + id IN (SELECT child_id FROM accessible_operations) + AND #{operation_predicate} ) - SELECT DISTINCT accessible_operations.operation_set_id, ops.unique_identifier - FROM accessible_operations - JOIN policy_elements ops ON ops.id = accessible_operations.child_id - WHERE ops.id IN (SELECT child_id FROM accessible_operations) + SELECT DISTINCT + ao.operation_set_id, + ops.unique_identifier + FROM operations ops + JOIN accessible_operations ao + on ao.child_id = ops.id SQL - sanitize_arg = [query, operation_set_ids] - - if operation_names - query << "AND ops.unique_identifier IN (?);" - sanitize_arg << operation_names - else - type = PolicyMachineStorageAdapter::ActiveRecord.class_for_type('operation').name - query << "AND ops.type = '#{type}';" - end - + sanitize_arg = [query] + query_args sanitized_query = sanitize_sql_for_assignment(sanitize_arg) # gives pairs of (opset_id, operation) representing all operations contained by an operation set From 4509817d7beab87b5a387ae65bd99e60248e6dd5 Mon Sep 17 00:00:00 2001 From: Kevin Jerinsky Date: Wed, 6 Mar 2024 13:02:55 -0500 Subject: [PATCH 2/2] upgrade PG for CTE features --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 836ebba..ee3c60b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,11 @@ language: ruby cache: bundler addons: - postgresql: "11" + postgresql: "12" apt: packages: - - postgresql-11 - - postgresql-client-11 + - postgresql-12 + - postgresql-client-12 env: global: