pg_eventstore 2.0.0 → 3.0.0
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/.rubocop.yml +10 -1
- data/CHANGELOG.md +186 -20
- data/README.md +25 -15
- data/db/migrations/10_setup_pg_cron.rb +1 -23
- data/db/migrations/15_create_streams_global_index.sql +17 -0
- data/db/migrations/16_populate_streams_global_index.rb +150 -0
- data/db/migrations/17_create_events_global_index.sql +62 -0
- data/db/migrations/18_populate_events_global_index.rb +124 -0
- data/db/migrations/19_populate_events_global_index_p2.rb +25 -0
- data/db/migrations/20_migrate_subscriptions_current_position.sql +19 -0
- data/db/migrations/21_create_partitions_stats.sql +2 -0
- data/db/migrations/22_drop_streams_sql_view.sql +2 -0
- data/db/migrations/23_adjust_partitions_indexes.sql +5 -0
- data/db/migrations/24_drop_legacy_events_indexes.sql +3 -0
- data/db/migrations/25_add_parent_partitions_info_to_partitions.sql +16 -0
- data/db/migrations/26_change_events_stream_revision_type.rb +35 -0
- data/db/migrations/27_drop_events_horizon.sql +3 -0
- data/db/migrations/28_create_maintenance_tasks.sql +8 -0
- data/db/migrations/29_create_event_markers.sql +35 -0
- data/db/migrations/30_improve_partitions_search_in_admin_ui.rb +24 -0
- data/db/migrations/31_drop_events_id_default_value.sql +1 -0
- data/db/migrations/32_create_parittions_triggers.sql +101 -0
- data/docs/AGENTS.fragment.md +696 -0
- data/docs/admin_ui.md +3 -1
- data/docs/appending_events.md +110 -49
- data/docs/configuration.md +69 -36
- data/docs/event_tracing.md +55 -0
- data/docs/events_and_streams.md +54 -30
- data/docs/how_it_works.md +57 -16
- data/docs/linking_events.md +2 -1
- data/docs/maintenance.md +14 -5
- data/docs/multiple_commands.md +17 -8
- data/docs/reading_events.md +208 -43
- data/docs/reading_streams.md +50 -0
- data/docs/replication.md +99 -0
- data/docs/subscriptions.md +165 -35
- data/docs/writing_middleware.md +25 -8
- data/ext/pg_eventstore_ext/extconf.rb +5 -0
- data/ext/pg_eventstore_ext/pg_eventstore_ext.c +74 -0
- data/lib/pg_eventstore/async_runner.rb +63 -0
- data/lib/pg_eventstore/basic_config.rb +15 -0
- data/lib/pg_eventstore/chunks/chunk.rb +31 -0
- data/lib/pg_eventstore/chunks/read_api_events_index_chunk.rb +83 -0
- data/lib/pg_eventstore/chunks/replica_events_index_chunk.rb +35 -0
- data/lib/pg_eventstore/chunks/repository.rb +73 -0
- data/lib/pg_eventstore/chunks/subscription_checkpoint_chunk.rb +48 -0
- data/lib/pg_eventstore/chunks/subscription_events_index_chunk.rb +99 -0
- data/lib/pg_eventstore/chunks.rb +14 -0
- data/lib/pg_eventstore/client.rb +163 -50
- data/lib/pg_eventstore/commands/append.rb +62 -43
- data/lib/pg_eventstore/commands/delete_event.rb +7 -8
- data/lib/pg_eventstore/commands/delete_stream.rb +3 -3
- data/lib/pg_eventstore/commands/event_modifiers/prepare_link_event.rb +9 -7
- data/lib/pg_eventstore/commands/event_modifiers/prepare_regular_event.rb +12 -7
- data/lib/pg_eventstore/commands/link_to.rb +5 -5
- data/lib/pg_eventstore/commands/read.rb +23 -5
- data/lib/pg_eventstore/commands/read_grouped.rb +46 -0
- data/lib/pg_eventstore/commands/read_streams.rb +18 -0
- data/lib/pg_eventstore/commands/read_streams_paginated.rb +56 -0
- data/lib/pg_eventstore/commands/regular_stream_read_paginated.rb +4 -4
- data/lib/pg_eventstore/commands/revision_check/current_revision.rb +51 -0
- data/lib/pg_eventstore/commands/revision_check/event_type_revisions_comparison.rb +46 -0
- data/lib/pg_eventstore/commands/revision_check/expected_revision.rb +135 -0
- data/lib/pg_eventstore/commands/revision_check/stream_revision_check.rb +98 -0
- data/lib/pg_eventstore/commands/revision_check/stream_revision_comparison.rb +36 -0
- data/lib/pg_eventstore/commands/stream_revision.rb +14 -0
- data/lib/pg_eventstore/commands/system_stream_read_paginated.rb +4 -4
- data/lib/pg_eventstore/commands.rb +4 -2
- data/lib/pg_eventstore/config.rb +30 -9
- data/lib/pg_eventstore/connection.rb +21 -2
- data/lib/pg_eventstore/errors.rb +136 -10
- data/lib/pg_eventstore/event.rb +34 -2
- data/lib/pg_eventstore/event_deserializer.rb +5 -4
- data/lib/pg_eventstore/event_global_index.rb +118 -0
- data/lib/pg_eventstore/event_marker.rb +16 -0
- data/lib/pg_eventstore/event_marker_index.rb +25 -0
- data/lib/pg_eventstore/event_serializer.rb +6 -0
- data/lib/pg_eventstore/extensions/acts_as_configurable.rb +88 -0
- data/lib/pg_eventstore/extensions/options_defaults.rb +25 -0
- data/lib/pg_eventstore/extensions/options_extension.rb +2 -2
- data/lib/pg_eventstore/feature_marker.rb +18 -0
- data/lib/pg_eventstore/maintenance.rb +11 -6
- data/lib/pg_eventstore/middleware/event_tracing.rb +53 -0
- data/lib/pg_eventstore/partition.rb +6 -0
- data/lib/pg_eventstore/pg_connection.rb +70 -14
- data/lib/pg_eventstore/queries/event_marker_queries.rb +74 -0
- data/lib/pg_eventstore/queries/event_queries.rb +7 -93
- data/lib/pg_eventstore/queries/events_global_index_queries.rb +131 -0
- data/lib/pg_eventstore/queries/index_filtering_queries.rb +179 -0
- data/lib/pg_eventstore/queries/links_resolver.rb +4 -4
- data/lib/pg_eventstore/queries/maintenance_queries.rb +159 -42
- data/lib/pg_eventstore/queries/partition_queries.rb +45 -103
- data/lib/pg_eventstore/queries/replica_queries.rb +110 -0
- data/lib/pg_eventstore/queries/streams_global_index_queries.rb +163 -0
- data/lib/pg_eventstore/queries/transaction_queries.rb +52 -10
- data/lib/pg_eventstore/queries.rb +29 -1
- data/lib/pg_eventstore/query_builders/basic_filtering.rb +38 -5
- data/lib/pg_eventstore/query_builders/event_markers_filtering.rb +47 -0
- data/lib/pg_eventstore/query_builders/event_markers_index_filtering.rb +275 -0
- data/lib/pg_eventstore/query_builders/event_subscription_positions_filtering.rb +37 -0
- data/lib/pg_eventstore/query_builders/events_filtering.rb +15 -164
- data/lib/pg_eventstore/query_builders/events_global_index_filtering.rb +227 -0
- data/lib/pg_eventstore/query_builders/filters/collection.rb +324 -0
- data/lib/pg_eventstore/query_builders/filters/event_type_filter.rb +37 -0
- data/lib/pg_eventstore/query_builders/filters/filter_row.rb +54 -0
- data/lib/pg_eventstore/query_builders/filters/marker_filter.rb +20 -0
- data/lib/pg_eventstore/query_builders/filters/marker_filter_row.rb +49 -0
- data/lib/pg_eventstore/query_builders/filters/stream_filter.rb +48 -0
- data/lib/pg_eventstore/query_builders/index_based_events_filtering.rb +260 -0
- data/lib/pg_eventstore/query_builders/partitions_filtering.rb +175 -51
- data/lib/pg_eventstore/query_builders/read_cursor/stream_cursor.rb +122 -0
- data/lib/pg_eventstore/query_builders/streams_global_index_filtering.rb +83 -0
- data/lib/pg_eventstore/query_builders/subscription_events_filtering.rb +79 -0
- data/lib/pg_eventstore/query_strategy/async.rb +64 -0
- data/lib/pg_eventstore/query_strategy/foreground.rb +25 -0
- data/lib/pg_eventstore/query_strategy.rb +19 -0
- data/lib/pg_eventstore/raw_event.rb +46 -0
- data/lib/pg_eventstore/rspec/test_helpers.rb +21 -8
- data/lib/pg_eventstore/sql_builder.rb +87 -8
- data/lib/pg_eventstore/stream.rb +13 -16
- data/lib/pg_eventstore/stream_global_index.rb +28 -0
- data/lib/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rb +5 -17
- data/lib/pg_eventstore/subscriptions/callback_handlers/events_subscription_position_worker_handlers.rb +36 -0
- data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rb +12 -0
- data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rb +21 -7
- data/lib/pg_eventstore/subscriptions/events_processor.rb +20 -18
- data/lib/pg_eventstore/subscriptions/events_processor_consumer/multiple.rb +63 -0
- data/lib/pg_eventstore/subscriptions/events_processor_consumer/replica.rb +68 -0
- data/lib/pg_eventstore/subscriptions/events_processor_consumer/single.rb +62 -0
- data/lib/pg_eventstore/subscriptions/events_processor_consumer.rb +44 -0
- data/lib/pg_eventstore/subscriptions/events_subscription_position_worker.rb +68 -0
- data/lib/pg_eventstore/subscriptions/queries/event_subscription_position_queries.rb +177 -0
- data/lib/pg_eventstore/subscriptions/queries/subscription_queries.rb +78 -54
- data/lib/pg_eventstore/subscriptions/replica_subscription_handler.rb +140 -0
- data/lib/pg_eventstore/subscriptions/replica_subscription_runner.rb +9 -0
- data/lib/pg_eventstore/subscriptions/subscription.rb +2 -1
- data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/collection.rb +36 -0
- data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/index_read_strategy.rb +82 -0
- data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/replication_strategy.rb +75 -0
- data/lib/pg_eventstore/subscriptions/subscription_feed_strategy.rb +31 -0
- data/lib/pg_eventstore/subscriptions/subscription_feeder.rb +24 -0
- data/lib/pg_eventstore/subscriptions/subscription_handler_performance.rb +4 -2
- data/lib/pg_eventstore/subscriptions/subscription_runner.rb +20 -9
- data/lib/pg_eventstore/subscriptions/subscription_runner_commands/reset_position.rb +1 -1
- data/lib/pg_eventstore/subscriptions/subscription_runners_feeder.rb +9 -18
- data/lib/pg_eventstore/subscriptions/subscriptions_lifecycle.rb +0 -12
- data/lib/pg_eventstore/subscriptions/subscriptions_manager.rb +74 -14
- data/lib/pg_eventstore/{subscriptions/synchronized_array.rb → synchronized_array.rb} +15 -0
- data/lib/pg_eventstore/tasks/setup.rake +2 -2
- data/lib/pg_eventstore/utils.rb +31 -0
- data/lib/pg_eventstore/version.rb +1 -1
- data/lib/pg_eventstore/web/application.rb +100 -16
- data/lib/pg_eventstore/web/paginator/base_collection.rb +5 -1
- data/lib/pg_eventstore/web/paginator/event_types_collection.rb +14 -4
- data/lib/pg_eventstore/web/paginator/events_collection.rb +29 -33
- data/lib/pg_eventstore/web/paginator/helpers.rb +16 -9
- data/lib/pg_eventstore/web/paginator/markers_collection.rb +48 -0
- data/lib/pg_eventstore/web/paginator/stream_contexts_collection.rb +13 -2
- data/lib/pg_eventstore/web/paginator/stream_ids_collection.rb +21 -11
- data/lib/pg_eventstore/web/paginator/stream_names_collection.rb +18 -4
- data/lib/pg_eventstore/web/paginator/streams_collection.rb +95 -0
- data/lib/pg_eventstore/web/public/javascripts/pg_eventstore.js +49 -22
- data/lib/pg_eventstore/web/subscriptions/set_collection.rb +1 -1
- data/lib/pg_eventstore/web/subscriptions/subscriptions.rb +1 -1
- data/lib/pg_eventstore/web/subscriptions/with_state/set_collection.rb +1 -1
- data/lib/pg_eventstore/web/subscriptions/with_state/subscriptions.rb +1 -1
- data/lib/pg_eventstore/web/views/home/dashboard.erb +11 -9
- data/lib/pg_eventstore/web/views/home/partials/event_filter.erb +18 -5
- data/lib/pg_eventstore/web/views/home/partials/events.erb +38 -1
- data/lib/pg_eventstore/web/views/home/partials/markers_filter.erb +18 -0
- data/lib/pg_eventstore/web/views/layouts/application.erb +6 -0
- data/lib/pg_eventstore/web/views/streams/index.erb +110 -0
- data/lib/pg_eventstore/web/views/streams/partials/streams.erb +11 -0
- data/lib/pg_eventstore/web/views/subscriptions/index.erb +4 -1
- data/lib/pg_eventstore/web.rb +2 -0
- data/lib/pg_eventstore.rb +23 -60
- data/pg_eventstore.gemspec +6 -4
- data/sig/interfaces/_raw_events_handler.rbs +3 -0
- data/sig/interfaces/subscription_handler.rbs +1 -1
- data/sig/pg/result.rbs +9 -0
- data/sig/pg_eventstore/async_runner.rbs +13 -0
- data/sig/pg_eventstore/basic_config.rbs +9 -0
- data/sig/pg_eventstore/chunks/chunk.rbs +13 -0
- data/sig/pg_eventstore/chunks/read_api_events_index_chunk.rbs +30 -0
- data/sig/pg_eventstore/chunks/replica_events_index_chunk.rbs +11 -0
- data/sig/pg_eventstore/chunks/repository.rbs +22 -0
- data/sig/pg_eventstore/chunks/subscription_checkpoint_chunk.rbs +18 -0
- data/sig/pg_eventstore/chunks/subscription_events_index_chunk.rbs +37 -0
- data/sig/pg_eventstore/client.rbs +40 -42
- data/sig/pg_eventstore/commands/append.rbs +11 -25
- data/sig/pg_eventstore/commands/event_modifiers/prepare_link_event.rbs +9 -12
- data/sig/pg_eventstore/commands/event_modifiers/prepare_regular_event.rbs +5 -4
- data/sig/pg_eventstore/commands/link_to.rbs +6 -11
- data/sig/pg_eventstore/commands/read.rbs +2 -5
- data/sig/pg_eventstore/commands/read_grouped.rbs +7 -0
- data/sig/pg_eventstore/commands/read_streams.rbs +7 -0
- data/sig/pg_eventstore/commands/read_streams_paginated.rbs +16 -0
- data/sig/pg_eventstore/commands/regular_stream_read_paginated.rbs +9 -17
- data/sig/pg_eventstore/commands/revision_check/current_revision.rbs +25 -0
- data/sig/pg_eventstore/commands/revision_check/event_type_revisions_comparison.rbs +14 -0
- data/sig/pg_eventstore/commands/revision_check/expected_revision.rbs +67 -0
- data/sig/pg_eventstore/commands/revision_check/stream_revision_check.rbs +20 -0
- data/sig/pg_eventstore/commands/revision_check/stream_revision_comparison.rbs +9 -0
- data/sig/pg_eventstore/commands/stream_revision.rbs +7 -0
- data/sig/pg_eventstore/commands/system_stream_read_paginated.rbs +9 -14
- data/sig/pg_eventstore/config.rbs +15 -6
- data/sig/pg_eventstore/connection.rbs +11 -18
- data/sig/pg_eventstore/errors.rbs +64 -34
- data/sig/pg_eventstore/event.rbs +16 -2
- data/sig/pg_eventstore/event_deserializer.rbs +5 -10
- data/sig/pg_eventstore/event_global_index.rbs +60 -0
- data/sig/pg_eventstore/event_marker.rbs +9 -0
- data/sig/pg_eventstore/event_marker_index.rbs +12 -0
- data/sig/pg_eventstore/extensions/acts_as_configurable.rbs +29 -0
- data/sig/pg_eventstore/extensions/options_defaults.rbs +7 -0
- data/sig/pg_eventstore/feature_marker.rbs +10 -0
- data/sig/pg_eventstore/maintenance.rbs +12 -8
- data/sig/pg_eventstore/middleware/event_trace.rbs +14 -0
- data/sig/pg_eventstore/partition.rbs +2 -4
- data/sig/pg_eventstore/pg_connection.rbs +8 -0
- data/sig/pg_eventstore/queries/event_marker_queries.rbs +21 -0
- data/sig/pg_eventstore/queries/event_queries.rbs +4 -36
- data/sig/pg_eventstore/queries/events_global_index_queries.rbs +37 -0
- data/sig/pg_eventstore/queries/index_filtering_queries.rbs +50 -0
- data/sig/pg_eventstore/queries/links_resolver.rbs +5 -9
- data/sig/pg_eventstore/queries/maintenance_queries.rbs +12 -9
- data/sig/pg_eventstore/queries/partition_queries.rbs +32 -67
- data/sig/pg_eventstore/queries/replica_queries.rbs +31 -0
- data/sig/pg_eventstore/queries/streams_global_index_queries.rbs +39 -0
- data/sig/pg_eventstore/queries/transaction_queries.rbs +2 -0
- data/sig/pg_eventstore/queries.rbs +11 -21
- data/sig/pg_eventstore/query_builders/basic_filtering.rbs +10 -3
- data/sig/pg_eventstore/query_builders/event_markers_filtering.rbs +17 -0
- data/sig/pg_eventstore/query_builders/event_markers_index_filtering.rbs +69 -0
- data/sig/pg_eventstore/query_builders/event_subscription_positions_filtering.rbs +15 -0
- data/sig/pg_eventstore/query_builders/events_filtering_query.rbs +9 -51
- data/sig/pg_eventstore/query_builders/events_global_index_filtering.rbs +68 -0
- data/sig/pg_eventstore/query_builders/filters/collection.rbs +84 -0
- data/sig/pg_eventstore/query_builders/filters/event_type_filter.rbs +19 -0
- data/sig/pg_eventstore/query_builders/filters/filter_row.rbs +21 -0
- data/sig/pg_eventstore/query_builders/filters/marker_filter.rbs +13 -0
- data/sig/pg_eventstore/query_builders/filters/marker_filter_row.rbs +19 -0
- data/sig/pg_eventstore/query_builders/filters/stream_filter.rbs +24 -0
- data/sig/pg_eventstore/query_builders/index_based_events_filtering.rbs +60 -0
- data/sig/pg_eventstore/query_builders/partitions_filtering.rbs +29 -10
- data/sig/pg_eventstore/query_builders/read_cursor/stream_cursor.rbs +47 -0
- data/sig/pg_eventstore/query_builders/streams_global_index_filtering.rbs +27 -0
- data/sig/pg_eventstore/query_builders/subscription_events_filtering.rbs +26 -0
- data/sig/pg_eventstore/query_strategy/async.rbs +17 -0
- data/sig/pg_eventstore/query_strategy/foreground.rbs +11 -0
- data/sig/pg_eventstore/query_strategy.rbs +7 -0
- data/sig/pg_eventstore/raw_event.rbs +20 -0
- data/sig/pg_eventstore/sql_builder.rbs +32 -10
- data/sig/pg_eventstore/stream.rbs +10 -18
- data/sig/pg_eventstore/stream_global_index.rbs +14 -0
- data/sig/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rbs +5 -4
- data/sig/pg_eventstore/subscriptions/callback_handlers/events_subscription_position_worker_handlers.rbs +9 -0
- data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rbs +17 -12
- data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rbs +17 -6
- data/sig/pg_eventstore/subscriptions/event_subscription_position_queries.rbs +30 -0
- data/sig/pg_eventstore/subscriptions/events_processor.rbs +12 -5
- data/sig/pg_eventstore/subscriptions/events_processor_consumer/multiple.rbs +17 -0
- data/sig/pg_eventstore/subscriptions/events_processor_consumer/replica.rbs +17 -0
- data/sig/pg_eventstore/subscriptions/events_processor_consumer/single.rbs +17 -0
- data/sig/pg_eventstore/subscriptions/events_processor_consumer.rbs +14 -0
- data/sig/pg_eventstore/subscriptions/events_subscription_position_worker.rbs +28 -0
- data/sig/pg_eventstore/subscriptions/queries/subscription_queries.rbs +7 -39
- data/sig/pg_eventstore/subscriptions/replica_subscription_handler.rbs +33 -0
- data/sig/pg_eventstore/subscriptions/replica_subscription_runner.rbs +4 -0
- data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/collection.rbs +14 -0
- data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/index_read_strategy.rbs +23 -0
- data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/replication_strategy.rbs +23 -0
- data/sig/pg_eventstore/subscriptions/subscription_feed_strategy.rbs +11 -0
- data/sig/pg_eventstore/subscriptions/subscription_feeder.rbs +13 -10
- data/sig/pg_eventstore/subscriptions/subscription_handler_performance.rbs +1 -1
- data/sig/pg_eventstore/subscriptions/subscription_runner.rbs +13 -2
- data/sig/pg_eventstore/subscriptions/subscription_runners_feeder.rbs +1 -8
- data/sig/pg_eventstore/subscriptions/subscriptions_lifecycle.rbs +4 -6
- data/sig/pg_eventstore/subscriptions/subscriptions_manager.rbs +29 -43
- data/sig/pg_eventstore/synchronized_array.rbs +4 -0
- data/sig/pg_eventstore/utils.rbs +10 -11
- data/sig/pg_eventstore/web/application.rbs +13 -3
- data/sig/pg_eventstore/web/paginator/base_collection.rbs +2 -0
- data/sig/pg_eventstore/web/paginator/event_types_collection.rbs +4 -0
- data/sig/pg_eventstore/web/paginator/events_collection.rbs +11 -11
- data/sig/pg_eventstore/web/paginator/helpers.rbs +6 -15
- data/sig/pg_eventstore/web/paginator/markers_collection.rbs +13 -0
- data/sig/pg_eventstore/web/paginator/stream_contexts_collection.rbs +4 -0
- data/sig/pg_eventstore/web/paginator/stream_names_collection.rbs +4 -0
- data/sig/pg_eventstore/web/paginator/streams_collection.rbs +30 -0
- data/sig/pg_eventstore.rbs +8 -26
- metadata +175 -20
- data/Dockerfile +0 -3
- data/lib/pg_eventstore/commands/all_stream_read_grouped.rb +0 -69
- data/lib/pg_eventstore/commands/regular_stream_read_grouped.rb +0 -31
- data/lib/pg_eventstore/subscriptions/queries/subscription_service_queries.rb +0 -78
- data/lib/pg_eventstore/web/views/home/partials/system_stream_filter.erb +0 -15
- data/sig/pg_eventstore/commands/all_stream_read_grouped.rbs +0 -16
- data/sig/pg_eventstore/commands/regular_stream_read_grouped.rbs +0 -8
- data/sig/pg_eventstore/subscriptions/queries/subscription_service_queries.rbs +0 -19
- data/sig/pg_eventstore/subscriptions/synchronized_array.rbs +0 -4
- /data/sig/interfaces/{_raw_event_handler.rbs → raw_event_handler.rbs} +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
module QueryBuilders
|
|
5
|
+
module Filters
|
|
6
|
+
# @!visibility private
|
|
7
|
+
class MarkerFilterRow
|
|
8
|
+
include Extensions::OptionsExtension
|
|
9
|
+
include Extensions::OptionsDefaults
|
|
10
|
+
|
|
11
|
+
# @!attribute stream_filter
|
|
12
|
+
# @return [PgEventstore::QueryBuilders::Filters::StreamFilter, nil]
|
|
13
|
+
attribute(:stream_filter)
|
|
14
|
+
# @!attribute stream_filter
|
|
15
|
+
# @return [PgEventstore::QueryBuilders::Filters::MarkerFilter]
|
|
16
|
+
attribute(:marker_filter)
|
|
17
|
+
|
|
18
|
+
# @return [Array<PgEventstore::QueryBuilders::Filters::MarkerFilterRow>]
|
|
19
|
+
def flatten
|
|
20
|
+
return [dup] if marker_filter.markers.size == 1
|
|
21
|
+
|
|
22
|
+
marker_filter.markers.map do |marker|
|
|
23
|
+
marker_filter = MarkerFilter.new(event_type: self.marker_filter.event_type, markers: [marker])
|
|
24
|
+
self.class.new(stream_filter:, marker_filter:)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Event type is ambiguous in case we can't tell which partition it belongs to. We **can** tell the exact
|
|
29
|
+
# partition of the given event type only when we have context and stream name as well.
|
|
30
|
+
# @return [Boolean]
|
|
31
|
+
def ambiguous_event_type?
|
|
32
|
+
return true if !stream_filter.nil? && !stream_filter.stream? && marker_filter.event_type.nil?
|
|
33
|
+
|
|
34
|
+
(stream_filter.nil? || stream_filter.context?) && !marker_filter.event_type.nil?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @return [PgEventstore::QueryBuilders::Filters::FilterRow]
|
|
38
|
+
def to_filter_row
|
|
39
|
+
if marker_filter.event_type
|
|
40
|
+
event_type_filter = EventTypeFilter.new(event_type: marker_filter.event_type, prefix: false)
|
|
41
|
+
FilterRow.new(stream_filter:, event_type_filters: [event_type_filter])
|
|
42
|
+
else
|
|
43
|
+
FilterRow.new(stream_filter:, event_type_filters: [])
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
module QueryBuilders
|
|
5
|
+
module Filters
|
|
6
|
+
# @!visibility private
|
|
7
|
+
class StreamFilter
|
|
8
|
+
include Extensions::OptionsExtension
|
|
9
|
+
include Extensions::OptionsDefaults
|
|
10
|
+
|
|
11
|
+
# @!attribute context
|
|
12
|
+
# @return [String]
|
|
13
|
+
attribute(:context)
|
|
14
|
+
# @!attribute stream_name
|
|
15
|
+
# @return [String, nil]
|
|
16
|
+
attribute(:stream_name)
|
|
17
|
+
# @!attribute stream_id
|
|
18
|
+
# @return [String, nil]
|
|
19
|
+
attribute(:stream_id)
|
|
20
|
+
|
|
21
|
+
# @return [Boolean]
|
|
22
|
+
def context?
|
|
23
|
+
stream_name.nil? && stream_id.nil?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @return [Boolean]
|
|
27
|
+
def stream_name?
|
|
28
|
+
!stream_name.nil? && stream_id.nil?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Boolean]
|
|
32
|
+
def stream?
|
|
33
|
+
!stream_name.nil? && !stream_id.nil?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @return [Hash]
|
|
37
|
+
def to_partition_h
|
|
38
|
+
{ context:, stream_name: }.compact
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Hash]
|
|
42
|
+
def to_h
|
|
43
|
+
{ context:, stream_name:, stream_id: }.compact
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
module QueryBuilders
|
|
5
|
+
class IndexBasedEventsFiltering
|
|
6
|
+
include BasicFiltering
|
|
7
|
+
|
|
8
|
+
# @return [Integer]
|
|
9
|
+
DEFAULT_LIMIT = 1_000
|
|
10
|
+
# @return [String]
|
|
11
|
+
ABSTRACT_TABLE_NAME = 'events_index'
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
# @param stream [PgEventstore::Stream]
|
|
15
|
+
# @param expected_revision [PgEventstore::Commands::RevisionCheck::ExpectedRevision::EventTypeRevision]
|
|
16
|
+
# @return [PgEventstore::SQLBuilder]
|
|
17
|
+
def sql_builder_for_event_type_revision_validation(stream, expected_revision)
|
|
18
|
+
cursor = QueryBuilders::ReadCursor::StreamCursor.from_stream_and_options(
|
|
19
|
+
stream, { direction: :desc, max_count: 1 }
|
|
20
|
+
)
|
|
21
|
+
filters_collection = Filters::Collection.from_stream_and_options(
|
|
22
|
+
stream, { filter: { event_types: [expected_revision.event_type] } }
|
|
23
|
+
)
|
|
24
|
+
rows = filters_collection.collection
|
|
25
|
+
Utils.assert!(rows.size == 1, filters_collection.inspect)
|
|
26
|
+
|
|
27
|
+
EventsGlobalIndexFiltering.for_revision_validation_per_type(
|
|
28
|
+
rows.first, cursor, expected_revision.sequence_number
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param stream [PgEventstore::Stream]
|
|
33
|
+
# @param expected_revision [PgEventstore::Commands::RevisionCheck::ExpectedRevision::EventTypeRevisionWithMarkers]
|
|
34
|
+
# @return [PgEventstore::SQLBuilder]
|
|
35
|
+
def sql_builder_for_event_type_with_markers_revision_validation(stream, expected_revision)
|
|
36
|
+
cursor = QueryBuilders::ReadCursor::StreamCursor.from_stream_and_options(
|
|
37
|
+
stream, { direction: :desc, max_count: 1 }
|
|
38
|
+
)
|
|
39
|
+
filters_collection = Filters::Collection.from_stream_and_options(
|
|
40
|
+
stream,
|
|
41
|
+
{
|
|
42
|
+
filter: {
|
|
43
|
+
event_types: [{ type: expected_revision.event_type, markers: expected_revision.markers }],
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
rows = filters_collection.collection
|
|
48
|
+
Utils.assert!(rows.size == 1, filters_collection.inspect)
|
|
49
|
+
|
|
50
|
+
builders = rows.first.flatten.map do |flattened|
|
|
51
|
+
EventMarkersIndexFiltering.for_revision_validation_per_type(
|
|
52
|
+
flattened, cursor, expected_revision.sequence_number
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
final = SQLBuilder.new.select('*')
|
|
56
|
+
final.from(SQLBuilder.union_builders(builders, mode: :union_distinct))
|
|
57
|
+
final.order('stream_revision desc')
|
|
58
|
+
final.limit(1)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @param stream [PgEventstore::Stream]
|
|
62
|
+
# @param expected_revision [PgEventstore::Commands::RevisionCheck::ExpectedRevision::MarkersRevision]
|
|
63
|
+
# @return [PgEventstore::SQLBuilder]
|
|
64
|
+
def sql_builder_for_markers_revision_validation(stream, expected_revision)
|
|
65
|
+
cursor = QueryBuilders::ReadCursor::StreamCursor.from_stream_and_options(
|
|
66
|
+
stream, { direction: :desc, max_count: 1 }
|
|
67
|
+
)
|
|
68
|
+
filters_collection = Filters::Collection.from_stream_and_options(
|
|
69
|
+
stream, { filter: { event_types: [{ markers: expected_revision.markers }] } }
|
|
70
|
+
)
|
|
71
|
+
rows = filters_collection.collection
|
|
72
|
+
Utils.assert!(rows.size == 1, filters_collection.inspect)
|
|
73
|
+
|
|
74
|
+
builders = rows.first.flatten.map do |flattened|
|
|
75
|
+
EventMarkersIndexFiltering.for_revision_validation_per_type(
|
|
76
|
+
flattened, cursor, expected_revision.sequence_number
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
final = SQLBuilder.new.select('*')
|
|
80
|
+
final.from(SQLBuilder.union_builders(builders, mode: :union_distinct))
|
|
81
|
+
final.order('stream_revision desc')
|
|
82
|
+
final.limit(1)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @param filter_rows [Array<PgEventstore::QueryBuilders::Filters::FilterRow,
|
|
86
|
+
# PgEventstore::QueryBuilders::Filters::MarkerFilterRow>]
|
|
87
|
+
# @param cursor [PgEventstore::QueryBuilders::ReadCursor::StreamCursor]
|
|
88
|
+
# @return [PgEventstore::SQLBuilder]
|
|
89
|
+
def sql_builder_for_read_grouped(filter_rows, cursor)
|
|
90
|
+
cursor = cursor.dup
|
|
91
|
+
cursor.max_count = 1
|
|
92
|
+
has_markers = false
|
|
93
|
+
builders = filter_rows.flat_map do |filter_row|
|
|
94
|
+
case filter_row
|
|
95
|
+
when Filters::FilterRow
|
|
96
|
+
filter_row.flatten.map do |flattened|
|
|
97
|
+
EventsGlobalIndexFiltering.for_read_common(flattened, cursor)
|
|
98
|
+
end
|
|
99
|
+
when Filters::MarkerFilterRow
|
|
100
|
+
has_markers ||= true
|
|
101
|
+
filter_row.flatten.map do |flattened|
|
|
102
|
+
EventMarkersIndexFiltering.for_read_common(flattened, cursor)
|
|
103
|
+
end
|
|
104
|
+
else
|
|
105
|
+
Utils.missing_implementation!(filter_row)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
union_builders(builders, cursor, mode: has_markers ? :union_distinct : :union_all, requires_limit: false)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @param filter_rows [Array<PgEventstore::QueryBuilders::Filters::FilterRow,
|
|
112
|
+
# PgEventstore::QueryBuilders::Filters::MarkerFilterRow>]
|
|
113
|
+
# @param cursor [PgEventstore::QueryBuilders::ReadCursor::StreamCursor]
|
|
114
|
+
# @return [PgEventstore::SQLBuilder]
|
|
115
|
+
def sql_builder_for_read_common(filter_rows, cursor)
|
|
116
|
+
return EventsGlobalIndexFiltering.default_filtering(cursor).to_sql_builder if filter_rows.empty?
|
|
117
|
+
|
|
118
|
+
has_markers = false
|
|
119
|
+
builders = filter_rows.flat_map do |filter_row|
|
|
120
|
+
case filter_row
|
|
121
|
+
when Filters::FilterRow
|
|
122
|
+
filter_row.flatten.map do |flattened|
|
|
123
|
+
EventsGlobalIndexFiltering.for_read_common(flattened, cursor)
|
|
124
|
+
end
|
|
125
|
+
when Filters::MarkerFilterRow
|
|
126
|
+
has_markers ||= true
|
|
127
|
+
filter_row.flatten.map do |flattened|
|
|
128
|
+
EventMarkersIndexFiltering.for_read_common(flattened, cursor)
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
Utils.missing_implementation!(filter_row)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
union_builders(builders, cursor, mode: has_markers ? :union_distinct : :union_all)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# @param filter_rows [Array<PgEventstore::QueryBuilders::Filters::FilterRow,
|
|
138
|
+
# PgEventstore::QueryBuilders::Filters::MarkerFilterRow>]
|
|
139
|
+
# @return [PgEventstore::SQLBuilder]
|
|
140
|
+
def sql_builder_for_estimate_count(filter_rows)
|
|
141
|
+
cursor = ReadCursor::StreamCursor.from_options({})
|
|
142
|
+
if filter_rows.empty?
|
|
143
|
+
return EventsGlobalIndexFiltering.default_filtering(cursor).to_sql_builder.remove_limit.remove_order
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
has_markers = false
|
|
147
|
+
builders = filter_rows.flat_map do |filter_row|
|
|
148
|
+
case filter_row
|
|
149
|
+
when Filters::FilterRow
|
|
150
|
+
filter_row.flatten.map do |flattened|
|
|
151
|
+
EventsGlobalIndexFiltering.for_read_common(flattened, cursor)
|
|
152
|
+
end
|
|
153
|
+
when Filters::MarkerFilterRow
|
|
154
|
+
has_markers ||= true
|
|
155
|
+
filter_row.flatten.map do |flattened|
|
|
156
|
+
EventMarkersIndexFiltering.for_read_common(flattened, cursor)
|
|
157
|
+
end
|
|
158
|
+
else
|
|
159
|
+
Utils.missing_implementation!(filter_row)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
builders.each { _1.remove_limit.remove_order }
|
|
163
|
+
top_builder = SQLBuilder.new.select('*')
|
|
164
|
+
top_builder.from(SQLBuilder.union_builders(builders, mode: has_markers ? :union_distinct : :union_all))
|
|
165
|
+
top_builder
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# @param filter_rows [Array<PgEventstore::QueryBuilders::Filters::FilterRow,
|
|
169
|
+
# PgEventstore::QueryBuilders::Filters::MarkerFilterRow>]
|
|
170
|
+
# @return [PgEventstore::SQLBuilder]
|
|
171
|
+
def sql_builder_for_subscriptions(filter_rows)
|
|
172
|
+
if filter_rows.empty?
|
|
173
|
+
sql_builder = EventsGlobalIndexFiltering.new.tap(&:for_subscription).to_sql_builder
|
|
174
|
+
return finalize_subscription_builders([sql_builder])
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
builders = []
|
|
178
|
+
grouped = filter_rows.group_by(&:class)
|
|
179
|
+
grouped.each_value do |rows|
|
|
180
|
+
case rows.first
|
|
181
|
+
when Filters::FilterRow
|
|
182
|
+
filtering = EventsGlobalIndexFiltering.new
|
|
183
|
+
filtering.for_subscription
|
|
184
|
+
rows.each(&filtering.method(:add_filter_row))
|
|
185
|
+
builders.push(filtering.to_sql_builder)
|
|
186
|
+
when Filters::MarkerFilterRow
|
|
187
|
+
filtering = EventMarkersIndexFiltering.new
|
|
188
|
+
filtering.for_subscription
|
|
189
|
+
rows.each(&filtering.method(:add_marker_filter_row))
|
|
190
|
+
builders.push(filtering.to_sql_builder)
|
|
191
|
+
else
|
|
192
|
+
Utils.missing_implementation!(rows.first)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
finalize_subscription_builders(builders)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
private
|
|
200
|
+
|
|
201
|
+
# @param builders [Array<PgEventstore::SQLBuilder>]
|
|
202
|
+
# @return [PgEventstore::SQLBuilder]
|
|
203
|
+
def finalize_subscription_builders(builders)
|
|
204
|
+
return builders.first if builders.size == 1
|
|
205
|
+
|
|
206
|
+
final = SQLBuilder.new.select(
|
|
207
|
+
'events_idx.global_position, events_idx.event_type_partition_id, events_idx.subscription_position'
|
|
208
|
+
)
|
|
209
|
+
final.from(SQLBuilder.union_builders(builders, mode: :union_distinct), table_alias: 'events_idx')
|
|
210
|
+
final.order('events_idx.subscription_position')
|
|
211
|
+
final.limit('max_count')
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# @param builders [Array<PgEventstore::SQLBuilder>]
|
|
215
|
+
# @param cursor [PgEventstore::QueryBuilders::ReadCursor::StreamCursor]
|
|
216
|
+
# @param mode [Symbol]
|
|
217
|
+
# @param requires_limit [Boolean]
|
|
218
|
+
# @return [PgEventstore::SQLBuilder]
|
|
219
|
+
def union_builders(builders, cursor, mode:, requires_limit: true)
|
|
220
|
+
return builders.first if builders.size == 1
|
|
221
|
+
|
|
222
|
+
union_builder = SQLBuilder.union_builders(builders, mode:)
|
|
223
|
+
top_filtering = new
|
|
224
|
+
# Union builder always has fixed columns in SELECT (global_position and event_type_partition_id). Thus,
|
|
225
|
+
# define SystemStreamOptions that is resolved to the sorting by global_position instead of possible
|
|
226
|
+
# sorting by stream_revision which may not be present among the columns list
|
|
227
|
+
cursor = ReadCursor::StreamCursor.from_options(direction: cursor.direction, max_count: cursor.max_count)
|
|
228
|
+
top_filtering.add_global_position_direction(cursor.direction)
|
|
229
|
+
top_filtering.add_limit(cursor.max_count) if requires_limit
|
|
230
|
+
top_filtering.to_sql_builder.from(union_builder)
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def initialize
|
|
235
|
+
@sql_builder = SQLBuilder.new
|
|
236
|
+
@sql_builder.select('global_position, event_type_partition_id')
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def to_table_name
|
|
240
|
+
''
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def to_sql_builder
|
|
244
|
+
@sql_builder
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# @param direction [String, Symbol, nil]
|
|
248
|
+
# @return [void]
|
|
249
|
+
def add_global_position_direction(direction)
|
|
250
|
+
@sql_builder.order("global_position #{SQL_DIRECTIONS[direction]}")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# @param limit [Integer, nil]
|
|
254
|
+
# @return [void]
|
|
255
|
+
def add_limit(limit)
|
|
256
|
+
@sql_builder.limit(limit || DEFAULT_LIMIT)
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
@@ -3,88 +3,212 @@
|
|
|
3
3
|
module PgEventstore
|
|
4
4
|
module QueryBuilders
|
|
5
5
|
# @!visibility private
|
|
6
|
-
class PartitionsFiltering
|
|
6
|
+
class PartitionsFiltering
|
|
7
|
+
include BasicFiltering
|
|
8
|
+
|
|
7
9
|
# @return [String]
|
|
8
10
|
TABLE_NAME = 'partitions'
|
|
9
|
-
private_constant :TABLE_NAME
|
|
10
11
|
|
|
11
12
|
class << self
|
|
12
|
-
# @param
|
|
13
|
-
# @
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
# @param filters_collection [PgEventstore::QueryBuilders::Filters::Collection]
|
|
14
|
+
# @param scope [Symbol] what kind of partition we want to receive. Available options are :event_type, :context,
|
|
15
|
+
# :stream_name and :auto. In :auto mode the scope will be calculated based on stream_filters and event_filters
|
|
16
|
+
# @return [PgEventstore::SQLBuilder]
|
|
17
|
+
def assemble_sql_builder(filters_collection, scope: :event_type)
|
|
18
|
+
if filters_collection.has_event_types?
|
|
19
|
+
# When event type filters are present - they apply constraints as is. Thus, we can't look up partitions by
|
|
20
|
+
# stream attributes separately.
|
|
21
|
+
filtering = new
|
|
22
|
+
filters_collection.collection.each(&filtering.method(:add_filter_row))
|
|
23
|
+
set_partitions_scope(filtering, has_stream_name_filter?(filters_collection), true, scope)
|
|
24
|
+
else
|
|
25
|
+
# When event type filters are absent - we can look up partitions by context and context/stream_name
|
|
26
|
+
# separately, thus potentially producing one-to-one mapping of filter-to-partition with :auto scope. For
|
|
27
|
+
# example, let's say we have stream attributes filter like
|
|
28
|
+
# [{ context: 'FooCtx', stream_name: 'Bar'}, { context: 'BarCtx' }], then we would be able to look up
|
|
29
|
+
# partitions by the exact match, returning only two of them according to the provided filters - stream
|
|
30
|
+
# partition for first filter and context partition for second filter.
|
|
31
|
+
builders = filters_collection.collection.map do |filter_row|
|
|
32
|
+
filtering = new
|
|
33
|
+
filtering.add_filter_row(filter_row)
|
|
34
|
+
set_partitions_scope(filtering, filter_row.stream_filter.stream_name?, false, scope)
|
|
35
|
+
end
|
|
19
36
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
stream_attrs in { stream_name: String | NilClass => stream_name }
|
|
27
|
-
{ context:, stream_name: }
|
|
37
|
+
sql_builder = SQLBuilder.union_builders(builders) if builders.any?
|
|
38
|
+
sql_builder ||
|
|
39
|
+
begin
|
|
40
|
+
filtering = new
|
|
41
|
+
set_partitions_scope(filtering, has_stream_name_filter?(filters_collection), false, scope)
|
|
42
|
+
end
|
|
28
43
|
end
|
|
29
|
-
streams || []
|
|
30
44
|
end
|
|
31
45
|
|
|
32
|
-
# @param
|
|
46
|
+
# @param filter_row [PgEventstore::QueryBuilders::Filters::FilterRow]
|
|
47
|
+
# @param scope [Symbol]
|
|
48
|
+
# @return [PgEventstore::SQLBuilder]
|
|
49
|
+
def from_filter_row(filter_row, scope: :event_type)
|
|
50
|
+
filtering = new
|
|
51
|
+
filtering.add_filter_row(filter_row)
|
|
52
|
+
has_stream_name_filter = filter_row.stream_filter&.stream_name? || false
|
|
53
|
+
has_event_type_filters = filter_row.event_type_filters.any?
|
|
54
|
+
set_partitions_scope(filtering, has_stream_name_filter, has_event_type_filters, scope)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
# @param filters_collection [PgEventstore::QueryBuilders::Filters::Collection]
|
|
33
60
|
# @return [Boolean]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
61
|
+
# rubocop:disable Naming/PredicatePrefix
|
|
62
|
+
def has_stream_name_filter?(filters_collection)
|
|
63
|
+
filters_collection.collection.any? { |filter_row| filter_row.stream_filter&.stream_name? }
|
|
64
|
+
end
|
|
65
|
+
# rubocop:enable Naming/PredicatePrefix
|
|
66
|
+
|
|
67
|
+
# @param partitions_filtering [PgEventstore::QueryBuilders::PartitionsFiltering]
|
|
68
|
+
# @param has_stream_name_filters [Boolean]
|
|
69
|
+
# @param has_event_type_filters [Boolean]
|
|
70
|
+
# @param scope [Symbol]
|
|
71
|
+
# @return [PgEventstore::SQLBuilder]
|
|
72
|
+
def set_partitions_scope(partitions_filtering, has_stream_name_filters, has_event_type_filters, scope)
|
|
73
|
+
case scope
|
|
74
|
+
when :event_type
|
|
75
|
+
partitions_filtering.with_event_types
|
|
76
|
+
partitions_filtering.order_by_event_type
|
|
77
|
+
partitions_filtering.to_sql_builder
|
|
78
|
+
when :stream_name
|
|
79
|
+
filter = QueryBuilders::PartitionsFiltering.new
|
|
80
|
+
filter.without_event_types
|
|
81
|
+
filter.order_by_stream_name
|
|
82
|
+
table_name = filter.to_table_name
|
|
83
|
+
builder = filter.to_sql_builder
|
|
84
|
+
builder.where(
|
|
85
|
+
"(#{table_name}.context, #{table_name}.stream_name) in ?",
|
|
86
|
+
partitions_filtering.
|
|
87
|
+
to_sql_builder.
|
|
88
|
+
unselect.
|
|
89
|
+
select(<<~SQL)
|
|
90
|
+
distinct on (#{table_name}.context, #{table_name}.stream_name)
|
|
91
|
+
#{table_name}.context, #{table_name}.stream_name
|
|
92
|
+
SQL
|
|
93
|
+
)
|
|
94
|
+
when :context
|
|
95
|
+
filter = QueryBuilders::PartitionsFiltering.new
|
|
96
|
+
filter.without_event_types
|
|
97
|
+
filter.without_stream_names
|
|
98
|
+
filter.order_by_context
|
|
99
|
+
builder = filter.to_sql_builder
|
|
100
|
+
builder.where(
|
|
101
|
+
"#{filter.to_table_name}.context in ?",
|
|
102
|
+
partitions_filtering.
|
|
103
|
+
to_sql_builder.
|
|
104
|
+
unselect.
|
|
105
|
+
select("distinct on (#{filter.to_table_name}.context) #{filter.to_table_name}.context")
|
|
106
|
+
)
|
|
107
|
+
when :auto
|
|
108
|
+
if has_event_type_filters
|
|
109
|
+
set_partitions_scope(partitions_filtering, has_stream_name_filters, has_event_type_filters, :event_type)
|
|
110
|
+
elsif has_stream_name_filters
|
|
111
|
+
set_partitions_scope(partitions_filtering, has_stream_name_filters, has_event_type_filters, :stream_name)
|
|
112
|
+
else
|
|
113
|
+
set_partitions_scope(partitions_filtering, has_stream_name_filters, has_event_type_filters, :context)
|
|
114
|
+
end
|
|
115
|
+
else
|
|
116
|
+
Utils.missing_implementation!(scope)
|
|
117
|
+
end
|
|
43
118
|
end
|
|
44
119
|
end
|
|
45
120
|
|
|
121
|
+
def initialize
|
|
122
|
+
@sql_builder = SQLBuilder.new.select("#{to_table_name}.*").from(to_table_name)
|
|
123
|
+
@has_event_types = []
|
|
124
|
+
@has_stream_names = []
|
|
125
|
+
@wants_event_type = false
|
|
126
|
+
@wants_stream_name = false
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def to_sql_builder
|
|
130
|
+
if @wants_event_type && (@has_event_types.empty? || !@has_event_types.all?)
|
|
131
|
+
@sql_builder.where("#{to_table_name}.event_type IS NOT NULL")
|
|
132
|
+
end
|
|
133
|
+
if @wants_stream_name && (@has_stream_names.empty? || !@has_stream_names.all?)
|
|
134
|
+
@sql_builder.where("#{to_table_name}.stream_name IS NOT NULL")
|
|
135
|
+
end
|
|
136
|
+
@sql_builder
|
|
137
|
+
end
|
|
138
|
+
|
|
46
139
|
# @return [String]
|
|
47
140
|
def to_table_name
|
|
48
141
|
TABLE_NAME
|
|
49
142
|
end
|
|
50
143
|
|
|
51
|
-
# @param
|
|
52
|
-
# @
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
stream_attrs.compact!
|
|
59
|
-
sql = stream_attrs.map do |attr, _|
|
|
60
|
-
"#{to_table_name}.#{attr} = ?"
|
|
61
|
-
end.join(' AND ')
|
|
62
|
-
@sql_builder.where_or(sql, *stream_attrs.values)
|
|
63
|
-
end
|
|
144
|
+
# @param filter_row [PgEventstore::QueryBuilders::Filters::FilterRow]
|
|
145
|
+
# @return [void]
|
|
146
|
+
def add_filter_row(filter_row)
|
|
147
|
+
stream_filter = filter_row.stream_filter
|
|
148
|
+
event_type_filters = filter_row.event_type_filters
|
|
149
|
+
@has_stream_names.push(stream_filter&.stream_name? || false)
|
|
150
|
+
@has_event_types.push(event_type_filters.any?)
|
|
64
151
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
152
|
+
stream_parts_filters = []
|
|
153
|
+
event_types_filters = []
|
|
154
|
+
stream_filter&.to_partition_h&.each do |attr, value|
|
|
155
|
+
stream_parts_filters.push(["#{to_table_name}.#{attr} = ?", value])
|
|
156
|
+
end
|
|
157
|
+
event_type_filters.each do |event_type_filter|
|
|
158
|
+
comparison_part = event_type_filter.prefix? ? 'like' : '='
|
|
159
|
+
event_types_filters.push(
|
|
160
|
+
["#{to_table_name}.event_type #{comparison_part} ?", event_type_filter.to_sql_value]
|
|
161
|
+
)
|
|
162
|
+
end
|
|
69
163
|
|
|
70
|
-
|
|
164
|
+
stream_parts_filters_query, stream_parts_filters_values = stream_parts_filters.transpose
|
|
165
|
+
event_types_query, event_types_values = event_types_filters.transpose
|
|
166
|
+
sql = ''
|
|
167
|
+
sql += stream_parts_filters_query.join(' and ') if stream_parts_filters_query&.any?
|
|
168
|
+
sql += ' and ' if sql != '' && event_types_query&.any?
|
|
169
|
+
sql += "(#{event_types_query.join(' or ')})" if event_types_query&.any?
|
|
170
|
+
@sql_builder.where_or(sql, *stream_parts_filters_values, *event_types_values)
|
|
171
|
+
nil
|
|
71
172
|
end
|
|
72
173
|
|
|
73
|
-
# @return [
|
|
174
|
+
# @return [void]
|
|
74
175
|
def with_event_types
|
|
75
|
-
@
|
|
176
|
+
@wants_event_type = true
|
|
76
177
|
end
|
|
77
178
|
|
|
179
|
+
# @return [void]
|
|
78
180
|
def with_stream_names
|
|
79
|
-
@
|
|
181
|
+
@wants_stream_name = true
|
|
80
182
|
end
|
|
81
183
|
|
|
184
|
+
# @return [void]
|
|
82
185
|
def without_event_types
|
|
83
|
-
@sql_builder.where(
|
|
186
|
+
@sql_builder.where("#{to_table_name}.event_type IS NULL")
|
|
187
|
+
nil
|
|
84
188
|
end
|
|
85
189
|
|
|
190
|
+
# @return [void]
|
|
86
191
|
def without_stream_names
|
|
87
|
-
@sql_builder.where(
|
|
192
|
+
@sql_builder.where("#{to_table_name}.stream_name IS NULL")
|
|
193
|
+
nil
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# @return [void]
|
|
197
|
+
def order_by_event_type
|
|
198
|
+
@sql_builder.order("#{to_table_name}.event_type asc, #{to_table_name}.id asc")
|
|
199
|
+
nil
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# @return [void]
|
|
203
|
+
def order_by_stream_name
|
|
204
|
+
@sql_builder.order("#{to_table_name}.context asc, #{to_table_name}.stream_name asc")
|
|
205
|
+
nil
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# @return [void]
|
|
209
|
+
def order_by_context
|
|
210
|
+
@sql_builder.order("#{to_table_name}.context asc")
|
|
211
|
+
nil
|
|
88
212
|
end
|
|
89
213
|
end
|
|
90
214
|
end
|