elasticgraph-warehouse 1.0.3.rc1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1c3e7a01b4bc1644e72c24ee57f20429918ecb3852a3bc9d6a6b304a7fb76349
4
+ data.tar.gz: e00d1206b3ab07a299160bbf21a1fb559ecdda4c315c949e22bae52c645a20ea
5
+ SHA512:
6
+ metadata.gz: 7846c4170015d7dd8ccee7655a24855fe48ee52e5ebd30d1c0bebb59795e7e02d71a1af899db13c1d692ba0d6af8e2ce1a2ecab7b8f5870015a4cf5074e64085
7
+ data.tar.gz: 1eb9780eba947bc4cc5fa1a3fb588c52fd8bf0b4b11987ddae3a79f0b9c9f40595bb409a2c56f893d8990ef5547b98be419c6412024899578ce39158564e26d3
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 - 2026 Block, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # ElasticGraph::Warehouse
2
+
3
+ An ElasticGraph extension that generates Data Warehouse table configurations from ElasticGraph schemas.
4
+
5
+ This extension enables seamless integration with data warehouse systems like Apache Hive, AWS Athena,
6
+ and similar SQL-based analytical platforms by automatically generating DDL and configuration files.
7
+
8
+ ## Dependency Diagram
9
+
10
+ ```mermaid
11
+ graph LR;
12
+ classDef targetGemStyle fill:#FADBD8,stroke:#EC7063,color:#000,stroke-width:2px;
13
+ classDef otherEgGemStyle fill:#A9DFBF,stroke:#2ECC71,color:#000;
14
+ classDef externalGemStyle fill:#E0EFFF,stroke:#70A1D7,color:#2980B9;
15
+ elasticgraph-warehouse["elasticgraph-warehouse"];
16
+ class elasticgraph-warehouse targetGemStyle;
17
+ elasticgraph-support["elasticgraph-support"];
18
+ elasticgraph-warehouse --> elasticgraph-support;
19
+ class elasticgraph-support otherEgGemStyle;
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ First, add `elasticgraph-warehouse` to your `Gemfile`, alongside the other ElasticGraph gems:
25
+
26
+ ```diff
27
+ diff --git a/Gemfile b/Gemfile
28
+ index 4a5ef1e..5c16c2b 100644
29
+ --- a/Gemfile
30
+ +++ b/Gemfile
31
+ @@ -8,6 +8,7 @@ gem "elasticgraph-query_registry", *elasticgraph_details
32
+
33
+ # Can be elasticgraph-elasticsearch or elasticgraph-opensearch based on the datastore you want to use.
34
+ gem "elasticgraph-opensearch", *elasticgraph_details
35
+ +gem "elasticgraph-warehouse", *elasticgraph_details
36
+
37
+ gem "httpx", "~> 1.3"
38
+
39
+ ```
40
+
41
+ Next, update your `Rakefile` so that `ElasticGraph::Warehouse::SchemaDefinition::APIExtension` is
42
+ used as one of the `schema_definition_extension_modules`:
43
+
44
+ ```diff
45
+ diff --git a/Rakefile b/Rakefile
46
+ index 2943335..26633c3 100644
47
+ --- a/Rakefile
48
+ +++ b/Rakefile
49
+ @@ -1,5 +1,6 @@
50
+ project_root = File.expand_path(__dir__)
51
+
52
+ +require "elastic_graph/warehouse/schema_definition/api_extension"
53
+ require "elastic_graph/local/rake_tasks"
54
+ require "elastic_graph/query_registry/rake_tasks"
55
+ require "rspec/core/rake_task"
56
+ @@ -12,6 +13,8 @@ ElasticGraph::Local::RakeTasks.new(
57
+ local_config_yaml: settings_file,
58
+ path_to_schema: "#{project_root}/config/schema.rb"
59
+ ) do |tasks|
60
+ + tasks.schema_definition_extension_modules = [ElasticGraph::Warehouse::SchemaDefinition::APIExtension]
61
+ +
62
+ # Set this to true once you're beyond the prototyping stage.
63
+ tasks.enforce_json_schema_version = false
64
+
65
+ ```
66
+
67
+ After running `bundle exec rake schema_artifacts:dump`, a `data_warehouse.yaml` file will be
68
+ generated containing SQL `CREATE TABLE` statements for each indexed type.
69
+
70
+ ## Schema Definition Options
71
+
72
+ ### Custom Table Names
73
+
74
+ By default, warehouse tables use the same name as the index. You can customize the table name
75
+ using the `warehouse_table` method:
76
+
77
+ ```ruby
78
+ # in config/schema/widget.rb
79
+
80
+ ElasticGraph.define_schema do |schema|
81
+ schema.object_type "Widget" do |t|
82
+ t.field "id", "ID"
83
+ t.field "name", "String"
84
+
85
+ t.index "widgets" do |i|
86
+ i.warehouse_table "widget_records" # Customize the warehouse table name
87
+ end
88
+ end
89
+ end
90
+ ```
91
+
92
+ ### Custom Scalar Types
93
+
94
+ Built-in ElasticGraph scalar types are automatically mapped to appropriate warehouse column types.
95
+ For custom scalar types, you must specify the warehouse column type:
96
+
97
+ ```ruby
98
+ # in config/schema/money.rb
99
+
100
+ ElasticGraph.define_schema do |schema|
101
+ schema.scalar_type "Money" do |t|
102
+ t.mapping type: "long"
103
+ t.json_schema type: "integer"
104
+ t.warehouse_column type: "BIGINT"
105
+ end
106
+ end
107
+ ```
108
+
109
+ ## Type Mappings
110
+
111
+ The extension automatically converts ElasticGraph types to warehouse column types:
112
+
113
+ | ElasticGraph Type | Warehouse Type |
114
+ |-------------------|----------------|
115
+ | `Boolean` | `BOOLEAN` |
116
+ | `Cursor` | `STRING` |
117
+ | `Date` | `DATE` |
118
+ | `DateTime` | `TIMESTAMP` |
119
+ | `Float` | `FLOAT` |
120
+ | `ID` | `STRING` |
121
+ | `Int` | `INT` |
122
+ | `JsonSafeLong` | `BIGINT` |
123
+ | `LocalTime` | `STRING` |
124
+ | `LongString` | `BIGINT` |
125
+ | `String` | `STRING` |
126
+ | `TimeZone` | `STRING` |
127
+ | `Untyped` | `STRING` |
128
+
129
+ Additionally:
130
+ - List types become `ARRAY<type>` (e.g., `[String!]!` becomes `ARRAY<STRING>`)
131
+ - Object types become `STRUCT<field1 type1, field2 type2, ...>`
132
+ - Nested arrays are supported (e.g., `[[Int!]!]!` becomes `ARRAY<ARRAY<INT>>`)
@@ -0,0 +1,72 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/warehouse/schema_definition/factory_extension"
10
+ require "elastic_graph/warehouse/schema_definition/scalar_type_extension"
11
+ require "elastic_graph/warehouse/schema_definition/enum_type_extension"
12
+ require "elastic_graph/warehouse/schema_definition/object_interface_and_union_extension"
13
+
14
+ module ElasticGraph
15
+ module Warehouse
16
+ # Namespace for all Warehouse schema definition support.
17
+ #
18
+ # {SchemaDefinition::APIExtension} is the primary entry point and should be used as a schema definition extension module.
19
+ module SchemaDefinition
20
+ # Module designed to be extended onto an {ElasticGraph::SchemaDefinition::API} instance
21
+ # to add Data Warehouse configuration generation capabilities.
22
+ #
23
+ # To use this module, pass it in `schema_definition_extension_modules` when defining your {ElasticGraph::Local::RakeTasks}.
24
+ #
25
+ # @example Define local rake tasks with this extension module
26
+ # require "elastic_graph/warehouse/schema_definition/api_extension"
27
+ #
28
+ # ElasticGraph::Local::RakeTasks.new(
29
+ # local_config_yaml: "config/settings/local.yaml",
30
+ # path_to_schema: "config/schema.rb"
31
+ # ) do |tasks|
32
+ # tasks.schema_definition_extension_modules = [
33
+ # ElasticGraph::Warehouse::SchemaDefinition::APIExtension
34
+ # ]
35
+ # end
36
+ module APIExtension
37
+ # Maps built-in ElasticGraph scalar types to their warehouse column types.
38
+ COLUMN_TYPES_BY_BUILT_IN_SCALAR_TYPE = {
39
+ "Boolean" => "BOOLEAN",
40
+ "Cursor" => "STRING",
41
+ "Date" => "DATE",
42
+ "DateTime" => "TIMESTAMP",
43
+ "Float" => "FLOAT",
44
+ "ID" => "STRING",
45
+ "Int" => "INT",
46
+ "JsonSafeLong" => "BIGINT",
47
+ "LocalTime" => "STRING",
48
+ "LongString" => "BIGINT",
49
+ "String" => "STRING",
50
+ "TimeZone" => "STRING",
51
+ "Untyped" => "STRING"
52
+ }.freeze
53
+
54
+ # Extends the API with warehouse functionality when this module is extended.
55
+ #
56
+ # @param api [ElasticGraph::SchemaDefinition::API] the API instance to extend
57
+ # @return [void]
58
+ # @api private
59
+ def self.extended(api)
60
+ api.factory.extend FactoryExtension
61
+
62
+ api.on_built_in_types do |type|
63
+ case type
64
+ when ScalarTypeExtension
65
+ type.warehouse_column type: COLUMN_TYPES_BY_BUILT_IN_SCALAR_TYPE.fetch(type.name)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,23 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ module ElasticGraph
10
+ module Warehouse
11
+ module SchemaDefinition
12
+ # Extends {ElasticGraph::SchemaDefinition::SchemaElements::EnumType} to add warehouse column type conversion.
13
+ module EnumTypeExtension
14
+ # Returns the warehouse column type representation for this enum type.
15
+ #
16
+ # @return [String] the SQL type string "STRING"
17
+ def to_warehouse_column_type
18
+ "STRING"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,130 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/warehouse/schema_definition/enum_type_extension"
10
+ require "elastic_graph/warehouse/schema_definition/index_extension"
11
+ require "elastic_graph/warehouse/schema_definition/object_interface_and_union_extension"
12
+ require "elastic_graph/warehouse/schema_definition/results_extension"
13
+ require "elastic_graph/warehouse/schema_definition/scalar_type_extension"
14
+ require "elastic_graph/warehouse/schema_definition/schema_artifact_manager_extension"
15
+
16
+ module ElasticGraph
17
+ module Warehouse
18
+ module SchemaDefinition
19
+ # Extension module applied to `ElasticGraph::SchemaDefinition::Factory` to add warehouse field type support.
20
+ #
21
+ # @api private
22
+ module FactoryExtension
23
+ # Creates a new enum type with warehouse extensions.
24
+ #
25
+ # @param name [String] the name of the enum type
26
+ # @yield [ElasticGraph::SchemaDefinition::SchemaElements::EnumType] the newly created enum type
27
+ # @return [ElasticGraph::SchemaDefinition::SchemaElements::EnumType] the created enum type
28
+ def new_enum_type(name)
29
+ super(name) do |type|
30
+ type.extend EnumTypeExtension
31
+ # :nocov: -- currently all invocations have a block
32
+ yield type if block_given?
33
+ # :nocov:
34
+ end
35
+ end
36
+
37
+ # Creates a new index with warehouse extensions.
38
+ # Automatically creates a warehouse table with the same name as the index
39
+ # unless one is explicitly defined or the index is excluded from the warehouse.
40
+ #
41
+ # @param name [String] the name of the index
42
+ # @param settings [Hash] additional settings for the index
43
+ # @param type [Object] the type this index is for
44
+ # @yield [ElasticGraph::SchemaDefinition::Indexing::Index] the newly created index (optional)
45
+ # @return [ElasticGraph::SchemaDefinition::Indexing::Index] the created index
46
+ def new_index(name, settings, type, &block)
47
+ super(name, settings, type) do |index|
48
+ extended_index = index.extend IndexExtension # : ::ElasticGraph::SchemaDefinition::Indexing::Index & IndexExtension
49
+ extended_index.warehouse_table(name)
50
+ block&.call(extended_index)
51
+ end
52
+ end
53
+
54
+ # Creates a new interface type with warehouse extensions.
55
+ #
56
+ # @param name [String] the name of the interface type
57
+ # @yield [ElasticGraph::SchemaDefinition::SchemaElements::InterfaceType] the newly created interface type
58
+ # @return [ElasticGraph::SchemaDefinition::SchemaElements::InterfaceType] the created interface type
59
+ def new_interface_type(name)
60
+ super(name) do |type|
61
+ type.extend ObjectInterfaceAndUnionExtension
62
+ # :nocov: -- currently all invocations have a block
63
+ yield type if block_given?
64
+ # :nocov:
65
+ end
66
+ end
67
+
68
+ # Creates a new object type with warehouse extensions.
69
+ #
70
+ # @param name [String] the name of the object type
71
+ # @yield [ElasticGraph::SchemaDefinition::SchemaElements::ObjectType] the newly created object type (optional)
72
+ # @return [ElasticGraph::SchemaDefinition::SchemaElements::ObjectType] the created object type
73
+ def new_object_type(name)
74
+ super(name) do |type|
75
+ type.extend ObjectInterfaceAndUnionExtension
76
+ # :nocov: -- currently all invocations have a block
77
+ yield type if block_given?
78
+ # :nocov:
79
+ end
80
+ end
81
+
82
+ # Creates a new scalar type with warehouse extensions.
83
+ #
84
+ # @param name [String] the name of the scalar type
85
+ # @yield [ElasticGraph::SchemaDefinition::SchemaElements::ScalarType] the newly created scalar type
86
+ # @return [ElasticGraph::SchemaDefinition::SchemaElements::ScalarType] the created scalar type
87
+ def new_scalar_type(name)
88
+ super(name) do |type|
89
+ type.extend ScalarTypeExtension
90
+ # :nocov: -- currently all invocations have a block
91
+ yield type if block_given?
92
+ # :nocov:
93
+ end
94
+ end
95
+
96
+ # Creates a new union type with warehouse extensions.
97
+ #
98
+ # @param name [String] the name of the union type
99
+ # @yield [ElasticGraph::SchemaDefinition::SchemaElements::UnionType] the newly created union type
100
+ # @return [ElasticGraph::SchemaDefinition::SchemaElements::UnionType] the created union type
101
+ def new_union_type(name)
102
+ super(name) do |type|
103
+ type.extend ObjectInterfaceAndUnionExtension
104
+ # :nocov: -- currently all invocations have a block
105
+ yield type if block_given?
106
+ # :nocov:
107
+ end
108
+ end
109
+
110
+ # Creates a new Results instance with warehouse extensions.
111
+ #
112
+ # @return [ElasticGraph::SchemaDefinition::Results] the created results instance
113
+ def new_results
114
+ super.tap do |results|
115
+ results.extend ResultsExtension
116
+ end
117
+ end
118
+
119
+ # Creates a new SchemaArtifactManager instance with warehouse extensions.
120
+ #
121
+ # @return [ElasticGraph::SchemaDefinition::SchemaArtifactManager] the created artifact manager
122
+ def new_schema_artifact_manager(...)
123
+ super.tap do |manager|
124
+ manager.extend SchemaArtifactManagerExtension
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,34 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ module ElasticGraph
10
+ module Warehouse
11
+ module SchemaDefinition
12
+ # Converts ElasticGraph field types to warehouse column types.
13
+ class FieldTypeConverter
14
+ # Converts a field type to a warehouse column type string.
15
+ #
16
+ # Handles both scalar and list types, unwrapping nullability and delegating to
17
+ # the resolved type's `to_warehouse_column_type` method. Supports
18
+ # nested arrays like `[[String!]]` which become `ARRAY<ARRAY<STRING>>`.
19
+ #
20
+ # @param field_type [Object] the field type to convert
21
+ # @return [String] the warehouse column type (e.g., "STRING", "ARRAY<INT>", "ARRAY<ARRAY<DOUBLE>>")
22
+ def self.convert(field_type)
23
+ unwrapped_type = field_type.unwrap_non_null
24
+
25
+ if unwrapped_type.list?
26
+ "ARRAY<#{convert(unwrapped_type.unwrap_list)}>"
27
+ else
28
+ unwrapped_type.resolved.to_warehouse_column_type
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,69 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/warehouse/schema_definition/warehouse_table"
10
+
11
+ module ElasticGraph
12
+ module Warehouse
13
+ module SchemaDefinition
14
+ # Extends {ElasticGraph::SchemaDefinition::Indexing::Index} to add warehouse table definition support.
15
+ module IndexExtension
16
+ # Returns the warehouse table definition for this index, if one has been defined via {#warehouse_table}.
17
+ #
18
+ # @return [WarehouseTable, nil] the warehouse table definition, or `nil` if none has been defined
19
+ # @dynamic warehouse_table_def
20
+ attr_reader :warehouse_table_def
21
+
22
+ # Defines a warehouse table for this index with a custom name.
23
+ #
24
+ # By default, a warehouse table is automatically created with the same name as the index.
25
+ # Use this method only when you need a different table name than the index name.
26
+ # To exclude an index from the warehouse entirely, use {#exclude_from_warehouse} instead.
27
+ #
28
+ # @param name [String] name of the warehouse table
29
+ # @return [void]
30
+ #
31
+ # @example Override the default warehouse table name
32
+ # ElasticGraph.define_schema do |schema|
33
+ # schema.object_type "Product" do |t|
34
+ # t.field "id", "ID"
35
+ # t.field "name", "String"
36
+ #
37
+ # t.index "products" do |i|
38
+ # # Override to use a different table name than "products"
39
+ # i.warehouse_table "store_products"
40
+ # end
41
+ # end
42
+ # end
43
+ def warehouse_table(name)
44
+ @warehouse_table_def = WarehouseTable.new(name: name, index: self)
45
+ end
46
+
47
+ # Excludes this index from the data warehouse configuration.
48
+ # This is useful when you have an index but don't want it to be included
49
+ # in the data warehouse.
50
+ #
51
+ # @return [void]
52
+ #
53
+ # @example Exclude an internal/test index from the warehouse
54
+ # ElasticGraph.define_schema do |schema|
55
+ # schema.object_type "InternalMetrics" do |t|
56
+ # t.field "id", "ID"
57
+ #
58
+ # t.index "internal_metrics" do |i|
59
+ # i.exclude_from_warehouse # This index won't be in the data warehouse
60
+ # end
61
+ # end
62
+ # end
63
+ def exclude_from_warehouse
64
+ @warehouse_table_def = nil
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/warehouse/schema_definition/field_type_converter"
10
+
11
+ module ElasticGraph
12
+ module Warehouse
13
+ module SchemaDefinition
14
+ # Extends {ElasticGraph::SchemaDefinition::SchemaElements::ObjectType},
15
+ # {ElasticGraph::SchemaDefinition::SchemaElements::InterfaceType}, and
16
+ # {ElasticGraph::SchemaDefinition::SchemaElements::UnionType} to add warehouse column type definition support.
17
+ module ObjectInterfaceAndUnionExtension
18
+ # Returns the warehouse column type representation for this object, interface, or union type.
19
+ #
20
+ # @return [String] a STRUCT SQL type containing all subfields
21
+ # @note For union types, the STRUCT includes all fields from all subtypes, following the same pattern used
22
+ # in the datastore mapping (see {ElasticGraph::SchemaDefinition::Indexing::FieldType::Union#to_mapping}).
23
+ def to_warehouse_column_type
24
+ subfields = indexing_fields_by_name_in_index.values.filter_map(&:to_indexing_field)
25
+
26
+ struct_field_expressions = subfields.map do |subfield|
27
+ warehouse_type = FieldTypeConverter.convert(subfield.type)
28
+ "#{subfield.name_in_index} #{warehouse_type}"
29
+ end.join(", ")
30
+
31
+ "STRUCT<#{struct_field_expressions}>"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/warehouse/schema_definition/warehouse_table"
10
+
11
+ module ElasticGraph
12
+ module Warehouse
13
+ module SchemaDefinition
14
+ # Extension module for {ElasticGraph::SchemaDefinition::Results} that adds warehouse configuration support.
15
+ #
16
+ # @private
17
+ module ResultsExtension
18
+ # Returns the warehouse configuration generated from the schema definition.
19
+ #
20
+ # @return [Hash<String, Hash>] a hash mapping table names to their configuration
21
+ def warehouse_config
22
+ @warehouse_config ||= generate_warehouse_config
23
+ end
24
+
25
+ private
26
+
27
+ # Generates warehouse configuration from indices that have warehouse table definitions.
28
+ #
29
+ # @return [Hash<String, Hash>] a hash mapping table names to their configuration
30
+ def generate_warehouse_config
31
+ tables = all_types
32
+ .filter_map { |type| (_ = type).index_def if type.respond_to?(:index_def) }
33
+ .filter_map(&:warehouse_table_def)
34
+ .sort_by(&:name)
35
+
36
+ {"tables" => tables.to_h { |table| [table.name, table.to_config] }}
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/errors"
10
+
11
+ module ElasticGraph
12
+ module Warehouse
13
+ module SchemaDefinition
14
+ # Extends {ElasticGraph::SchemaDefinition::SchemaElements::ScalarType} to add warehouse column type conversion.
15
+ module ScalarTypeExtension
16
+ # Warehouse column type configured on this scalar type.
17
+ # @dynamic warehouse_column_type
18
+ attr_reader :warehouse_column_type
19
+
20
+ # Configures warehouse column type for this scalar type.
21
+ #
22
+ # @param type [String] the warehouse column type (e.g., "TIMESTAMP", "BINARY")
23
+ # @return [String] the configured warehouse column type
24
+ def warehouse_column(type:)
25
+ @warehouse_column_type = type
26
+ end
27
+
28
+ # Returns the warehouse column type representation for this scalar type.
29
+ #
30
+ # @return [String] the SQL type string (e.g., "INT", "DOUBLE", "BOOLEAN", "STRING")
31
+ # @raise [RuntimeError] if warehouse_column_type has not been configured
32
+ # @note Built-in ElasticGraph scalar types are automatically configured with appropriate warehouse column types.
33
+ # Custom scalar types must explicitly call `warehouse_column` to specify their warehouse type.
34
+ def to_warehouse_column_type
35
+ warehouse_column_type || raise(Errors::SchemaError, "Warehouse column type not configured for scalar type `#{name}`. " \
36
+ 'To proceed, call `warehouse_column type: "TYPE"` on the scalar type definition.')
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/warehouse"
10
+
11
+ module ElasticGraph
12
+ module Warehouse
13
+ module SchemaDefinition
14
+ # Extension module for {ElasticGraph::SchemaDefinition::SchemaArtifactManager} that adds
15
+ # warehouse artifact generation support.
16
+ #
17
+ # @private
18
+ module SchemaArtifactManagerExtension
19
+ private
20
+
21
+ # Overrides the base `artifacts_from_schema_def` method to add warehouse artifacts.
22
+ #
23
+ # This method is called when computing the list of schema artifacts. It calls super
24
+ # to get the base artifacts, then appends the warehouse artifact if any warehouse
25
+ # tables are defined.
26
+ #
27
+ # @return [Array<ElasticGraph::SchemaDefinition::SchemaArtifact>] the list of schema artifacts
28
+ def artifacts_from_schema_def
29
+ base_artifacts = super
30
+ results = schema_definition_results # : ElasticGraph::SchemaDefinition::Results & ResultsExtension
31
+ warehouse_config = results.warehouse_config
32
+
33
+ # Only add the artifact if there are warehouse tables defined.
34
+ return base_artifacts if warehouse_config["tables"].empty?
35
+
36
+ warehouse_artifact = new_yaml_artifact(
37
+ DATA_WAREHOUSE_FILE,
38
+ warehouse_config,
39
+ extra_comment_lines: ["This file contains Data Warehouse configuration generated from the ElasticGraph schema."]
40
+ )
41
+
42
+ base_artifacts + [warehouse_artifact]
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,53 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/warehouse/schema_definition/field_type_converter"
10
+
11
+ module ElasticGraph
12
+ module Warehouse
13
+ module SchemaDefinition
14
+ # Represents a warehouse table configuration.
15
+ class WarehouseTable < ::Data.define(:name, :index)
16
+ # Converts the warehouse table to a configuration hash.
17
+ #
18
+ # @return [Hash] configuration hash with table_schema
19
+ def to_config
20
+ {
21
+ "table_schema" => table_schema
22
+ }
23
+ end
24
+
25
+ private
26
+
27
+ # Generates the SQL CREATE TABLE statement for this warehouse table.
28
+ #
29
+ # @return [String] SQL CREATE TABLE statement with all fields
30
+ def table_schema
31
+ fields = index.indexed_type
32
+ .indexing_fields_by_name_in_index
33
+ .values
34
+ .filter_map(&:to_indexing_field)
35
+ .map { |field| table_field(field) }
36
+ .join(",\n ")
37
+
38
+ <<~SQL.strip
39
+ CREATE TABLE IF NOT EXISTS #{name} (
40
+ #{fields}
41
+ )
42
+ SQL
43
+ end
44
+
45
+ def table_field(field)
46
+ field_name = field.name_in_index
47
+ warehouse_type = FieldTypeConverter.convert(field.type)
48
+ "#{field_name} #{warehouse_type}"
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,30 @@
1
+ # Copyright 2024 - 2026 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ module ElasticGraph
10
+ # Warehouse extension: adds Data Warehouse config generation to ElasticGraph.
11
+ #
12
+ # This gem follows the same extension pattern as elasticgraph-apollo, using factory extensions
13
+ # to add warehouse capabilities to schema elements.
14
+ #
15
+ # @example Using the warehouse extension
16
+ # require "elastic_graph/warehouse/schema_definition/api_extension"
17
+ #
18
+ # ElasticGraph::Local::RakeTasks.new(
19
+ # local_config_yaml: "config/settings/local.yaml",
20
+ # path_to_schema: "config/schema.rb"
21
+ # ) do |tasks|
22
+ # tasks.schema_definition_extension_modules = [
23
+ # ElasticGraph::Warehouse::SchemaDefinition::APIExtension
24
+ # ]
25
+ # end
26
+ module Warehouse
27
+ # The name of the generated data warehouse configuration file.
28
+ DATA_WAREHOUSE_FILE = "data_warehouse.yaml"
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elasticgraph-warehouse
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.3.rc1
5
+ platform: ruby
6
+ authors:
7
+ - Josh Wilson
8
+ - Myron Marston
9
+ - Block Engineering
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 1980-01-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: elasticgraph-schema_definition
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '='
19
+ - !ruby/object:Gem::Version
20
+ version: 1.0.3.rc1
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '='
26
+ - !ruby/object:Gem::Version
27
+ version: 1.0.3.rc1
28
+ - !ruby/object:Gem::Dependency
29
+ name: elasticgraph-support
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '='
33
+ - !ruby/object:Gem::Version
34
+ version: 1.0.3.rc1
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '='
40
+ - !ruby/object:Gem::Version
41
+ version: 1.0.3.rc1
42
+ email:
43
+ - joshuaw@squareup.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE.txt
49
+ - README.md
50
+ - lib/elastic_graph/warehouse.rb
51
+ - lib/elastic_graph/warehouse/schema_definition/api_extension.rb
52
+ - lib/elastic_graph/warehouse/schema_definition/enum_type_extension.rb
53
+ - lib/elastic_graph/warehouse/schema_definition/factory_extension.rb
54
+ - lib/elastic_graph/warehouse/schema_definition/field_type_converter.rb
55
+ - lib/elastic_graph/warehouse/schema_definition/index_extension.rb
56
+ - lib/elastic_graph/warehouse/schema_definition/object_interface_and_union_extension.rb
57
+ - lib/elastic_graph/warehouse/schema_definition/results_extension.rb
58
+ - lib/elastic_graph/warehouse/schema_definition/scalar_type_extension.rb
59
+ - lib/elastic_graph/warehouse/schema_definition/schema_artifact_manager_extension.rb
60
+ - lib/elastic_graph/warehouse/schema_definition/warehouse_table.rb
61
+ homepage: https://block.github.io/elasticgraph/
62
+ licenses:
63
+ - MIT
64
+ metadata:
65
+ bug_tracker_uri: https://github.com/block/elasticgraph/issues
66
+ changelog_uri: https://github.com/block/elasticgraph/releases/tag/v1.0.3.rc1
67
+ documentation_uri: https://block.github.io/elasticgraph/api-docs/v1.0.3.rc1/
68
+ homepage_uri: https://block.github.io/elasticgraph/
69
+ source_code_uri: https://github.com/block/elasticgraph/tree/v1.0.3.rc1/elasticgraph-warehouse
70
+ gem_category: extension
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '3.4'
79
+ - - "<"
80
+ - !ruby/object:Gem::Version
81
+ version: '4.1'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 4.0.3
89
+ specification_version: 4
90
+ summary: Extends ElasticGraph to support ingestion into a data warehouse.
91
+ test_files: []