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,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
module QueryBuilders
|
|
5
|
+
module ReadCursor
|
|
6
|
+
# @!visibility private
|
|
7
|
+
class StreamCursor
|
|
8
|
+
class RegularStreamCursor
|
|
9
|
+
include Extensions::OptionsExtension
|
|
10
|
+
include Extensions::OptionsDefaults
|
|
11
|
+
|
|
12
|
+
# @!attribute from_revision
|
|
13
|
+
# @return [Integer, nil]
|
|
14
|
+
attribute(:from_revision)
|
|
15
|
+
# @!attribute to_revision
|
|
16
|
+
# @return [Integer, nil]
|
|
17
|
+
attribute(:to_revision)
|
|
18
|
+
# @!attribute direction
|
|
19
|
+
# @return [String, Symbol, nil]
|
|
20
|
+
attribute(:direction)
|
|
21
|
+
# @!attribute max_count
|
|
22
|
+
# @return [Integer, nil]
|
|
23
|
+
attribute(:max_count)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class AllStreamCursor
|
|
27
|
+
include Extensions::OptionsExtension
|
|
28
|
+
include Extensions::OptionsDefaults
|
|
29
|
+
|
|
30
|
+
# @!attribute from_position
|
|
31
|
+
# @return [Integer, nil]
|
|
32
|
+
attribute(:from_position)
|
|
33
|
+
# @!attribute to_position
|
|
34
|
+
# @return [Integer, nil]
|
|
35
|
+
attribute(:to_position)
|
|
36
|
+
# @!attribute direction
|
|
37
|
+
# @return [String, Symbol, nil]
|
|
38
|
+
attribute(:direction)
|
|
39
|
+
# @!attribute max_count
|
|
40
|
+
# @return [Integer, nil]
|
|
41
|
+
attribute(:max_count)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class << self
|
|
45
|
+
# @param options [Hash]
|
|
46
|
+
# @option options [Integer, nil] :from_position
|
|
47
|
+
# @option options [Integer, nil] :to_position
|
|
48
|
+
# @option options [String, Symbol, nil] :direction
|
|
49
|
+
# @option options [Integer, nil] :max_count
|
|
50
|
+
# @return [PgEventstore::QueryBuilders::ReadCursor::StreamCursor]
|
|
51
|
+
def from_options(options)
|
|
52
|
+
new(AllStreamCursor.new(**options))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @param options [Hash]
|
|
56
|
+
# @option options [Integer, nil] :from_position for "all" stream
|
|
57
|
+
# @option options [Integer, nil] :to_position for "all" stream
|
|
58
|
+
# @option options [Integer, nil] :from_revision for regular stream
|
|
59
|
+
# @option options [Integer, nil] :to_revision for regular stream
|
|
60
|
+
# @option options [String, Symbol, nil] :direction
|
|
61
|
+
# @option options [Integer, nil] :max_count
|
|
62
|
+
# @return [PgEventstore::QueryBuilders::ReadCursor::StreamCursor]
|
|
63
|
+
def from_stream_and_options(stream, options)
|
|
64
|
+
return new(AllStreamCursor.new(**options)) if stream.all_stream?
|
|
65
|
+
|
|
66
|
+
new(RegularStreamCursor.new(**options))
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @param cursor [ReadCursor::RegularStreamCursor, ReadCursor::RegularStreamCursor]
|
|
71
|
+
def initialize(cursor)
|
|
72
|
+
@cursor = cursor
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @return [Integer, nil]
|
|
76
|
+
def from
|
|
77
|
+
case @cursor
|
|
78
|
+
when RegularStreamCursor
|
|
79
|
+
@cursor.from_revision
|
|
80
|
+
when AllStreamCursor
|
|
81
|
+
@cursor.from_position
|
|
82
|
+
else
|
|
83
|
+
Utils.missing_implementation!(@cursor)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @return [Integer, nil]
|
|
88
|
+
def to
|
|
89
|
+
case @cursor
|
|
90
|
+
when RegularStreamCursor
|
|
91
|
+
@cursor.to_revision
|
|
92
|
+
when AllStreamCursor
|
|
93
|
+
@cursor.to_position
|
|
94
|
+
else
|
|
95
|
+
Utils.missing_implementation!(@cursor)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# @return [String, Symbol, nil]
|
|
100
|
+
def direction
|
|
101
|
+
@cursor.direction
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @return [Integer, nil]
|
|
105
|
+
def max_count
|
|
106
|
+
@cursor.max_count
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# @param val [Integer, nil]
|
|
110
|
+
# @return [void]
|
|
111
|
+
def max_count=(val)
|
|
112
|
+
@cursor.max_count = val
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @return [Boolean]
|
|
116
|
+
def all_stream_cursor?
|
|
117
|
+
@cursor.is_a?(AllStreamCursor)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
module QueryBuilders
|
|
5
|
+
# @!visibility private
|
|
6
|
+
class StreamsGlobalIndexFiltering
|
|
7
|
+
include BasicFiltering
|
|
8
|
+
|
|
9
|
+
# @return [String]
|
|
10
|
+
PRIMARY_TABLE_NAME = 'streams_global_index'
|
|
11
|
+
# @return [Integer]
|
|
12
|
+
DEFAULT_LIMIT = 1000
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
# @param options [Hash]
|
|
16
|
+
# @option options [Integer, nil] :from_position
|
|
17
|
+
# @option options [Integer, nil] :max_count
|
|
18
|
+
# @option options [String, Symbol, nil] :direction
|
|
19
|
+
# @return [PgEventstore::SQLBuilder]
|
|
20
|
+
def sql_builder_for_basic_pagination(options)
|
|
21
|
+
streams_idx_filtering = QueryBuilders::StreamsGlobalIndexFiltering.new
|
|
22
|
+
streams_idx_filtering.from_position(options[:from_position], options[:direction])
|
|
23
|
+
streams_idx_filtering.limit(options[:max_count])
|
|
24
|
+
streams_idx_filtering.add_starting_position_direction(options[:direction])
|
|
25
|
+
streams_idx_filtering.to_sql_builder
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def initialize
|
|
30
|
+
@sql_builder = SQLBuilder.new.select("#{to_table_name}.*").from(to_table_name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_sql_builder
|
|
34
|
+
@sql_builder
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @return [String]
|
|
38
|
+
def to_table_name
|
|
39
|
+
PRIMARY_TABLE_NAME
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @param filter_row [PgEventstore::QueryBuilders::Filters::FilterRow]
|
|
43
|
+
# @return [void]
|
|
44
|
+
def add_filter_row(filter_row)
|
|
45
|
+
stream_filter = filter_row.stream_filter
|
|
46
|
+
raise ArgumentError, "Invalid stream filter: #{stream_filter}" unless stream_filter&.stream?
|
|
47
|
+
|
|
48
|
+
affected_partitions = PartitionsFiltering.from_filter_row(filter_row, scope: :stream_name)
|
|
49
|
+
builder = affected_partitions.select_id_only
|
|
50
|
+
@sql_builder.where_or('partition_id = ? and stream_id = ?', builder, stream_filter.stream_id)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @param position [Integer, nil]
|
|
54
|
+
# @param direction [Symbol, String, nil]
|
|
55
|
+
# @return [void]
|
|
56
|
+
def from_position(position, direction)
|
|
57
|
+
return if position.nil?
|
|
58
|
+
|
|
59
|
+
@sql_builder.where("starting_position #{direction_operator_from(direction)} ?", position)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @param limit [Integer, nil]
|
|
63
|
+
# @return [void]
|
|
64
|
+
def limit(limit)
|
|
65
|
+
@sql_builder.limit(limit || DEFAULT_LIMIT)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @param direction [Symbol, String, nil]
|
|
69
|
+
# @return [void]
|
|
70
|
+
def add_starting_position_direction(direction)
|
|
71
|
+
@sql_builder.order("#{to_table_name}.starting_position #{SQL_DIRECTIONS[direction]}")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
# @param direction [String, Symbol, nil]
|
|
77
|
+
# @return [String]
|
|
78
|
+
def direction_operator_from(direction)
|
|
79
|
+
SQL_DIRECTIONS[direction] == 'ASC' ? '>=' : '<='
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
module QueryBuilders
|
|
5
|
+
# @!visibility private
|
|
6
|
+
class SubscriptionEventsFiltering
|
|
7
|
+
include BasicFiltering
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
# @param id [integer]
|
|
11
|
+
# @param options [Hash]
|
|
12
|
+
# @option options [Integer] :from_position
|
|
13
|
+
# @option options [Integer] :to_position
|
|
14
|
+
# @option options [Integer] :max_count
|
|
15
|
+
# @return [PgEventstore::QueryBuilders::SubscriptionEventsFiltering]
|
|
16
|
+
def build(id, options)
|
|
17
|
+
index_filter = new(id)
|
|
18
|
+
index_filter.from_position(options[:from_position])
|
|
19
|
+
index_filter.to_position(options[:to_position])
|
|
20
|
+
index_filter.add_limit(options[:max_count])
|
|
21
|
+
index_filter
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @param subscription_id [Integer]
|
|
26
|
+
def initialize(subscription_id)
|
|
27
|
+
@subscription_id = subscription_id
|
|
28
|
+
@from_position = 0
|
|
29
|
+
@to_position = 0
|
|
30
|
+
@max_count = 0
|
|
31
|
+
@sql_builder = SQLBuilder.new.select("#{to_table_name}.*")
|
|
32
|
+
compute_from
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_sql_builder
|
|
36
|
+
compute_from
|
|
37
|
+
@sql_builder
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param position [Integer, nil]
|
|
41
|
+
# @return [void]
|
|
42
|
+
def from_position(position)
|
|
43
|
+
raise ArgumentError, 'position must be valid number' unless position.is_a?(Integer)
|
|
44
|
+
|
|
45
|
+
@from_position = position
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @param position [Integer, nil]
|
|
49
|
+
# @return [void]
|
|
50
|
+
def to_position(position)
|
|
51
|
+
raise ArgumentError, 'position must be valid number' unless position.is_a?(Integer)
|
|
52
|
+
|
|
53
|
+
@to_position = position
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param limit [Integer, nil]
|
|
57
|
+
# @return [void]
|
|
58
|
+
def add_limit(limit)
|
|
59
|
+
raise ArgumentError, 'limit must be valid number' unless limit.is_a?(Integer)
|
|
60
|
+
|
|
61
|
+
@max_count = limit
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [String]
|
|
65
|
+
def to_table_name
|
|
66
|
+
"subscription_#{@subscription_id}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def compute_from
|
|
72
|
+
@sql_builder.from(
|
|
73
|
+
"#{to_table_name}(#{@from_position}, #{@to_position}, #{@max_count})",
|
|
74
|
+
table_alias: to_table_name
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
module QueryStrategy
|
|
5
|
+
# @!visibility private
|
|
6
|
+
class Async
|
|
7
|
+
include QueryStrategy
|
|
8
|
+
|
|
9
|
+
# @param connection [PgEventstore::Connection]
|
|
10
|
+
def initialize(connection)
|
|
11
|
+
@connection = connection
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def exec(*)
|
|
15
|
+
run(:send_query, *)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def exec_params(*)
|
|
19
|
+
run(:send_query_params, *)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def run(method, *exec_args)
|
|
25
|
+
@connection.with do |conn|
|
|
26
|
+
conn.public_send(method, *exec_args)
|
|
27
|
+
loop do
|
|
28
|
+
conn.consume_input
|
|
29
|
+
break unless conn.is_busy
|
|
30
|
+
|
|
31
|
+
Fiber.yield
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
last_result = nil
|
|
35
|
+
while result = conn.get_result
|
|
36
|
+
# Check whether result is successful. Raises error if it is not.
|
|
37
|
+
# Related function is pg_result_check() in pg_result.c
|
|
38
|
+
result.check_result
|
|
39
|
+
last_result = result
|
|
40
|
+
end
|
|
41
|
+
last_result
|
|
42
|
+
rescue AsyncRunner::Cancellation
|
|
43
|
+
cancel_and_drain(conn)
|
|
44
|
+
Fiber.current.kill
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @param conn [PG::Connection]
|
|
49
|
+
# @return [void]
|
|
50
|
+
def cancel_and_drain(conn)
|
|
51
|
+
cancellation_error = conn.cancel
|
|
52
|
+
conn.sync_reset if cancellation_error
|
|
53
|
+
|
|
54
|
+
while (result = conn.get_result)
|
|
55
|
+
result.clear
|
|
56
|
+
end
|
|
57
|
+
rescue PG::Error
|
|
58
|
+
# We have unexpected error during the cancellation process. No need to try to restore the connection at this
|
|
59
|
+
# point and simply throw it out
|
|
60
|
+
@connection.discard_current_connection
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
module QueryStrategy
|
|
5
|
+
class Foreground
|
|
6
|
+
include QueryStrategy
|
|
7
|
+
|
|
8
|
+
def initialize(connection)
|
|
9
|
+
@connection = connection
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def exec(*exec_args)
|
|
13
|
+
@connection.with do |conn|
|
|
14
|
+
conn.exec(*exec_args)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def exec_params(*exec_args)
|
|
19
|
+
@connection.with do |conn|
|
|
20
|
+
conn.exec_params(*exec_args)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
# @!visibility private
|
|
5
|
+
module QueryStrategy
|
|
6
|
+
# @return [PG::Result]
|
|
7
|
+
def exec(*args)
|
|
8
|
+
raise NotImplementedError
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @return [PG::Result]
|
|
12
|
+
def exec_params(*args)
|
|
13
|
+
raise NotImplementedError
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
require_relative 'query_strategy/async'
|
|
19
|
+
require_relative 'query_strategy/foreground'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
# @!visibility private
|
|
5
|
+
class RawEvent
|
|
6
|
+
include Extensions::OptionsExtension
|
|
7
|
+
include Extensions::OptionsDefaults
|
|
8
|
+
|
|
9
|
+
# @!attribute id
|
|
10
|
+
# @return [String]
|
|
11
|
+
attribute(:id)
|
|
12
|
+
# @!attribute context
|
|
13
|
+
# @return [String]
|
|
14
|
+
attribute(:context)
|
|
15
|
+
# @!attribute stream_name
|
|
16
|
+
# @return [String]
|
|
17
|
+
attribute(:stream_name)
|
|
18
|
+
# @!attribute stream_id
|
|
19
|
+
# @return [String]
|
|
20
|
+
attribute(:stream_id)
|
|
21
|
+
# @!attribute global_position
|
|
22
|
+
# @return [Integer]
|
|
23
|
+
attribute(:global_position)
|
|
24
|
+
# @!attribute stream_revision
|
|
25
|
+
# @return [Integer]
|
|
26
|
+
attribute(:stream_revision)
|
|
27
|
+
# @!attribute data
|
|
28
|
+
# @return [Hash]
|
|
29
|
+
attribute(:data)
|
|
30
|
+
# @!attribute metadata
|
|
31
|
+
# @return [Hash]
|
|
32
|
+
attribute(:metadata)
|
|
33
|
+
# @!attribute link_partition_id
|
|
34
|
+
# @return [Integer, nil]
|
|
35
|
+
attribute(:link_partition_id)
|
|
36
|
+
# @!attribute created_at
|
|
37
|
+
# @return [Time]
|
|
38
|
+
attribute(:created_at)
|
|
39
|
+
# @!attribute type
|
|
40
|
+
# @return [String]
|
|
41
|
+
attribute(:type)
|
|
42
|
+
# @!attribute link_global_position
|
|
43
|
+
# @return [Integer, nil]
|
|
44
|
+
attribute(:link_global_position)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
module PgEventstore
|
|
4
4
|
module TestHelpers
|
|
5
5
|
class << self
|
|
6
|
-
def clean_up_db
|
|
7
|
-
clean_up_data
|
|
8
|
-
clean_up_partitions
|
|
6
|
+
def clean_up_db(config = :default)
|
|
7
|
+
clean_up_data(config)
|
|
8
|
+
clean_up_partitions(config)
|
|
9
|
+
clean_up_subscription_functions(config)
|
|
9
10
|
end
|
|
10
11
|
|
|
11
|
-
def clean_up_partitions
|
|
12
|
-
PgEventstore.connection.with do |conn|
|
|
12
|
+
def clean_up_partitions(config)
|
|
13
|
+
PgEventstore.connection(config).with do |conn|
|
|
13
14
|
# Dropping parent partition also drops all child partitions
|
|
14
15
|
conn.exec("select tablename from pg_tables where tablename like 'contexts_%'").each do |attrs|
|
|
15
16
|
conn.exec("drop table #{attrs['tablename']}")
|
|
@@ -17,8 +18,8 @@ module PgEventstore
|
|
|
17
18
|
end
|
|
18
19
|
end
|
|
19
20
|
|
|
20
|
-
def clean_up_data
|
|
21
|
-
tables_to_purge = PgEventstore.connection.with do |conn|
|
|
21
|
+
def clean_up_data(config)
|
|
22
|
+
tables_to_purge = PgEventstore.connection(config).with do |conn|
|
|
22
23
|
conn.exec(<<~SQL)
|
|
23
24
|
SELECT tablename
|
|
24
25
|
FROM pg_catalog.pg_tables
|
|
@@ -27,7 +28,19 @@ module PgEventstore
|
|
|
27
28
|
end
|
|
28
29
|
tables_to_purge = tables_to_purge.map { |attrs| attrs['tablename'] }
|
|
29
30
|
tables_to_purge.each do |table_name|
|
|
30
|
-
PgEventstore.connection.with { |c| c.exec("DELETE FROM #{table_name}") }
|
|
31
|
+
PgEventstore.connection(config).with { |c| c.exec("DELETE FROM #{table_name}") }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def clean_up_subscription_functions(config)
|
|
36
|
+
functions_to_purge = PgEventstore.connection(config).with do |conn|
|
|
37
|
+
conn.exec(<<~SQL)
|
|
38
|
+
SELECT proname FROM pg_proc WHERE proname LIKE 'subscription_%'
|
|
39
|
+
SQL
|
|
40
|
+
end
|
|
41
|
+
functions_to_purge = functions_to_purge.map { _1['proname'] }
|
|
42
|
+
functions_to_purge.each do |function_name|
|
|
43
|
+
PgEventstore.connection(config).with { |c| c.exec("drop function #{function_name}") }
|
|
31
44
|
end
|
|
32
45
|
end
|
|
33
46
|
end
|
|
@@ -6,16 +6,35 @@ module PgEventstore
|
|
|
6
6
|
class SQLBuilder
|
|
7
7
|
class << self
|
|
8
8
|
# @param builders [Array<PgEventstore::SQLBuilder>]
|
|
9
|
+
# @param mode [Symbol]
|
|
9
10
|
# @return [PgEventstore::SQLBuilder]
|
|
10
|
-
def union_builders(builders)
|
|
11
|
-
|
|
11
|
+
def union_builders(builders, mode: :union_all)
|
|
12
|
+
Utils.assert!(!builders.empty?, "Can't union empty array!")
|
|
13
|
+
|
|
14
|
+
union_builder = builders[1..].each_with_object(builders[0]) do |builder, first_builder|
|
|
12
15
|
first_builder.union(builder)
|
|
13
16
|
end
|
|
17
|
+
union_builder.union_mode = mode
|
|
18
|
+
union_builder
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @param builder [PgEventstore::SQLBuilder]
|
|
22
|
+
# @return [PgEventstore::SQLBuilder]
|
|
23
|
+
def wrap_union_builder(builder)
|
|
24
|
+
new.tap do |b|
|
|
25
|
+
b.select('*')
|
|
26
|
+
b.from(builder)
|
|
27
|
+
end
|
|
14
28
|
end
|
|
15
29
|
end
|
|
16
30
|
|
|
31
|
+
UNION_MODES = %i[union_all union_distinct intersect_all intersect_distinct].freeze
|
|
32
|
+
private_constant :UNION_MODES
|
|
33
|
+
|
|
17
34
|
# @return [Array<Object>] sql positional values
|
|
18
35
|
attr_reader :positional_values
|
|
36
|
+
# @return [String, nil]
|
|
37
|
+
attr_reader :table_alias
|
|
19
38
|
# @return [Integer]
|
|
20
39
|
attr_writer :positional_values_size
|
|
21
40
|
|
|
@@ -33,6 +52,8 @@ module PgEventstore
|
|
|
33
52
|
@positional_values = []
|
|
34
53
|
@positional_values_size = 0
|
|
35
54
|
@union_values = []
|
|
55
|
+
@union_mode = :union_all
|
|
56
|
+
@table_alias = nil
|
|
36
57
|
end
|
|
37
58
|
|
|
38
59
|
# @param sql [String]
|
|
@@ -42,6 +63,14 @@ module PgEventstore
|
|
|
42
63
|
self
|
|
43
64
|
end
|
|
44
65
|
|
|
66
|
+
# @return [PgEventstore::SQLBuilder]
|
|
67
|
+
def select_id_only
|
|
68
|
+
raise 'You have to call #from first' unless @table_alias
|
|
69
|
+
|
|
70
|
+
remove_order.unselect.select("#{@table_alias}.id")
|
|
71
|
+
self
|
|
72
|
+
end
|
|
73
|
+
|
|
45
74
|
# @return [self]
|
|
46
75
|
def unselect
|
|
47
76
|
@select_values.clear
|
|
@@ -64,10 +93,12 @@ module PgEventstore
|
|
|
64
93
|
self
|
|
65
94
|
end
|
|
66
95
|
|
|
67
|
-
# @param table_name [String
|
|
96
|
+
# @param table_name [String, SQLBuilder]
|
|
97
|
+
# @param table_alias [String, nil]
|
|
68
98
|
# @return [self]
|
|
69
|
-
def from(table_name)
|
|
99
|
+
def from(table_name, table_alias: nil)
|
|
70
100
|
@from_value = table_name
|
|
101
|
+
@table_alias = table_alias || (table_name.is_a?(SQLBuilder) ? table_name.table_alias : table_name)
|
|
71
102
|
self
|
|
72
103
|
end
|
|
73
104
|
|
|
@@ -92,10 +123,16 @@ module PgEventstore
|
|
|
92
123
|
self
|
|
93
124
|
end
|
|
94
125
|
|
|
95
|
-
# @param limit [Integer]
|
|
126
|
+
# @param limit [String, Integer]
|
|
96
127
|
# @return [self]
|
|
97
128
|
def limit(limit)
|
|
98
|
-
@limit_value =
|
|
129
|
+
@limit_value =
|
|
130
|
+
case limit
|
|
131
|
+
when String
|
|
132
|
+
limit.start_with?(/\d/) ? limit.to_i : PG::Connection.escape(limit)
|
|
133
|
+
else
|
|
134
|
+
limit
|
|
135
|
+
end
|
|
99
136
|
self
|
|
100
137
|
end
|
|
101
138
|
|
|
@@ -139,6 +176,34 @@ module PgEventstore
|
|
|
139
176
|
_to_exec_params
|
|
140
177
|
end
|
|
141
178
|
|
|
179
|
+
def dup
|
|
180
|
+
self.class.new.tap do |inst|
|
|
181
|
+
inst.instance_variable_set(:@select_values, @select_values.map(&:dup))
|
|
182
|
+
inst.instance_variable_set(:@from_value, @from_value&.dup)
|
|
183
|
+
inst.instance_variable_set(:@where_values, @where_values.dup.transform_values(&:dup))
|
|
184
|
+
inst.instance_variable_set(:@join_values, @join_values.map(&:dup))
|
|
185
|
+
inst.instance_variable_set(:@group_values, @group_values.map(&:dup))
|
|
186
|
+
inst.instance_variable_set(:@order_values, @order_values.map(&:dup))
|
|
187
|
+
inst.instance_variable_set(:@limit_value, @limit_value&.dup)
|
|
188
|
+
inst.instance_variable_set(:@offset_value, @offset_value&.dup)
|
|
189
|
+
inst.instance_variable_set(:@positional_values, @positional_values.map(&:dup))
|
|
190
|
+
inst.instance_variable_set(:@positional_values_size, @positional_values_size)
|
|
191
|
+
inst.instance_variable_set(:@union_values, @union_values.map(&:dup))
|
|
192
|
+
inst.instance_variable_set(:@union_mode, @union_mode.dup)
|
|
193
|
+
inst.instance_variable_set(:@table_alias, @table_alias.dup)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def union_builder?
|
|
198
|
+
@union_values.any?
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def union_mode=(val)
|
|
202
|
+
raise "Unknown UNION mode #{val.inspect}. Available modes are: #{UNION_MODES}" unless UNION_MODES.include?(val)
|
|
203
|
+
|
|
204
|
+
@union_mode = val
|
|
205
|
+
end
|
|
206
|
+
|
|
142
207
|
protected
|
|
143
208
|
|
|
144
209
|
# @return [[String, Array<_>]]
|
|
@@ -153,7 +218,7 @@ module PgEventstore
|
|
|
153
218
|
return @from_value if @from_value.is_a?(String)
|
|
154
219
|
|
|
155
220
|
sql = merge(@from_value)
|
|
156
|
-
"(#{sql}) #{@
|
|
221
|
+
"(#{sql}) #{@table_alias}"
|
|
157
222
|
end
|
|
158
223
|
|
|
159
224
|
private
|
|
@@ -178,7 +243,20 @@ module PgEventstore
|
|
|
178
243
|
union_parts += @union_values.map do |builder|
|
|
179
244
|
"(#{merge(builder)})"
|
|
180
245
|
end
|
|
181
|
-
|
|
246
|
+
union_mode_sql =
|
|
247
|
+
case @union_mode
|
|
248
|
+
when :union_all
|
|
249
|
+
'UNION ALL'
|
|
250
|
+
when :union_distinct
|
|
251
|
+
'UNION'
|
|
252
|
+
when :intersect_all
|
|
253
|
+
'INTERSECT ALL'
|
|
254
|
+
when :intersect_distinct
|
|
255
|
+
'INTERSECT'
|
|
256
|
+
else
|
|
257
|
+
Utils.missing_implementation!(@union_mode)
|
|
258
|
+
end
|
|
259
|
+
union_parts.join(" #{union_mode_sql} ")
|
|
182
260
|
end
|
|
183
261
|
|
|
184
262
|
# @return [String]
|
|
@@ -207,6 +285,7 @@ module PgEventstore
|
|
|
207
285
|
# @param builder [PgEventstore::SQLBuilder]
|
|
208
286
|
# @return [String]
|
|
209
287
|
def merge(builder)
|
|
288
|
+
builder = builder.dup
|
|
210
289
|
builder.positional_values_size = @positional_values_size
|
|
211
290
|
sql_query, positional_values = builder._to_exec_params
|
|
212
291
|
@positional_values.push(*positional_values)
|