Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ Gemfile.lock
tmp/*
pkg/*
coverage/
/modelgen/java-extractor/.gradle/
/modelgen/java-extractor/build/
/modelgen/java-extractor/.idea/
128 changes: 128 additions & 0 deletions modelgen/compare_model_shapes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# frozen_string_literal: true

require "json"

if ARGV.length != 3
warn <<~USAGE
Usage:
ruby modelgen/compare_model_shapes.rb \
<version> \
<old-model.rb> \
<new-model.rb>
USAGE

exit 1
end

version, old_path, new_path = ARGV

module Trino
module Client
module ModelVersions
end
end
end

module_name = :"V#{version.tr('.', '_')}"

def capture_shape(
module_name:,
path:
)
model_versions =
Trino::Client::ModelVersions

if model_versions.const_defined?(
module_name,
false,
)
model_versions.send(
:remove_const,
module_name,
)
end

load File.expand_path(path)

version_module = model_versions.const_get(
module_name,
false,
)

shape = {}

version_module
.constants(false)
.sort
.each do |constant_name|
value = version_module.const_get(
constant_name,
false,
)

next unless value.respond_to?(:members)

shape[constant_name.to_s] =
value.members.map(&:to_s)
end

model_versions.send(
:remove_const,
module_name,
)

shape
end

old_shape = capture_shape(
module_name: module_name,
path: old_path,
)

new_shape = capture_shape(
module_name: module_name,
path: new_path,
)

missing_models =
old_shape.keys - new_shape.keys

added_models =
new_shape.keys - old_shape.keys

missing_fields = {}
added_fields = {}

(old_shape.keys & new_shape.keys).each do |model|
old_fields = old_shape.fetch(model)
new_fields = new_shape.fetch(model)

missing = old_fields - new_fields
added = new_fields - old_fields

missing_fields[model] = missing \
unless missing.empty?

added_fields[model] = added \
unless added.empty?
end

result = {
missingModels: missing_models.sort,
addedModels: added_models.sort,
missingFields: missing_fields,
addedFields: added_fields,
}

puts JSON.pretty_generate(result)

has_regression =
!missing_models.empty? ||
!missing_fields.empty?

if has_regression
warn "Compatibility check failed."
exit 1
end

puts "Compatibility check passed."
62 changes: 62 additions & 0 deletions modelgen/generate_from_schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# frozen_string_literal: true

require "erb"
require "fileutils"
require "json"

require_relative "schema_formatter"

if ARGV.length != 3
warn <<~USAGE
Usage:
ruby modelgen/generate_from_schema.rb \
<version> \
<schema.json> \
<output.rb>
USAGE

exit 1
end

model_version, schema_path, output_path = ARGV

schema = JSON.parse(
File.read(schema_path),
)

schema_version = schema.fetch(
"trinoVersion",
)

unless schema_version == model_version
raise ArgumentError,
"Version mismatch: argument=#{model_version.inspect}, " \
"schema=#{schema_version.inspect}"
end

formatter = TrinoModels::SchemaFormatter.new(
schema,
)

@contents = formatter.format
@model_version = model_version

template_path = File.expand_path(
"model_versions.rb",
__dir__,
)

template = ERB.new(
File.read(template_path),
)

FileUtils.mkdir_p(
File.dirname(output_path),
)

File.write(
output_path,
template.result(binding),
)

puts "Generated #{output_path}."
83 changes: 83 additions & 0 deletions modelgen/java-extractor/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
plugins {
id 'application'
id 'java'
}

repositories {
mavenCentral()
}

def trinoVersion = providers
.gradleProperty('trinoVersion')
.getOrElse('483')

def javaVersion = providers
.gradleProperty('javaVersion')
.getOrElse('25')
.toInteger()

java {
toolchain {
languageVersion = JavaLanguageVersion.of(javaVersion)
}
}

dependencies {
implementation "io.trino:trino-client:${trinoVersion}"
implementation "io.trino:trino-main:${trinoVersion}"

implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jacksonVersion}"
implementation "com.fasterxml.jackson.module:jackson-module-parameter-names:${jacksonVersion}"

testImplementation platform('org.junit:junit-bom:5.11.4')
testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

application {
mainClass = 'org.trinoruby.modelgen.ModelExtractor'
}

test {
useJUnitPlatform()
}

tasks.register('extractModels', JavaExec) {
group = 'model generation'
description = 'Extracts Trino models into an intermediate JSON schema'

classpath = sourceSets.main.runtimeClasspath
mainClass = application.mainClass

def version = trinoVersion

def rootsFile = layout.projectDirectory.file(
"config/roots-${version}.txt"
)

def outputFile = layout.projectDirectory.file(
"../schemas/${version}.json"
)

args(
'--trino-version', version,
'--roots', rootsFile.asFile.absolutePath,
'--output', outputFile.asFile.absolutePath
)

doFirst {
println "Extractor Java: ${javaLauncher.get().executablePath}"
println "Trino version: ${version}"
println "Roots: ${rootsFile.asFile}"
println "Output: ${outputFile.asFile}"
}
}

tasks.register('printRuntimeClasspath') {
group = 'help'

doLast {
println sourceSets.main.runtimeClasspath.asPath
}
}
59 changes: 59 additions & 0 deletions modelgen/java-extractor/config/roots-351.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Trino REST API root model
# Fully qualified class name

io.trino.client.QueryResults
io.trino.execution.QueryInfo
io.trino.server.BasicQueryInfo

io.trino.sql.planner.plan.OutputNode
io.trino.sql.planner.plan.ProjectNode
io.trino.sql.planner.plan.TableScanNode
io.trino.sql.planner.plan.ValuesNode
io.trino.sql.planner.plan.AggregationNode
io.trino.sql.planner.plan.MarkDistinctNode
io.trino.sql.planner.plan.FilterNode
io.trino.sql.planner.plan.WindowNode
io.trino.sql.planner.plan.RowNumberNode
io.trino.sql.planner.plan.TopNRowNumberNode
io.trino.sql.planner.plan.LimitNode
io.trino.sql.planner.plan.DistinctLimitNode
io.trino.sql.planner.plan.TopNNode
io.trino.sql.planner.plan.SampleNode
io.trino.sql.planner.plan.SortNode
io.trino.sql.planner.plan.RemoteSourceNode
io.trino.sql.planner.plan.JoinNode
io.trino.sql.planner.plan.SemiJoinNode
io.trino.sql.planner.plan.SpatialJoinNode
io.trino.sql.planner.plan.IndexJoinNode
io.trino.sql.planner.plan.IndexSourceNode
io.trino.sql.planner.plan.TableWriterNode
io.trino.sql.planner.plan.DeleteNode
io.trino.sql.planner.plan.TableFinishNode
io.trino.sql.planner.plan.UnnestNode
io.trino.sql.planner.plan.ExchangeNode
io.trino.sql.planner.plan.UnionNode
io.trino.sql.planner.plan.IntersectNode
io.trino.sql.planner.plan.EnforceSingleRowNode
io.trino.sql.planner.plan.GroupIdNode
io.trino.sql.planner.plan.ExplainAnalyzeNode
io.trino.sql.planner.plan.ApplyNode
io.trino.sql.planner.plan.AssignUniqueId
io.trino.sql.planner.plan.CorrelatedJoinNode
io.trino.sql.planner.plan.StatisticsWriterNode
io.trino.metadata.AnalyzeTableHandle
io.trino.metadata.InsertTableHandle
io.trino.metadata.OutputTableHandle
io.trino.operator.ExchangeClientStatus
io.trino.operator.JoinOperatorInfo
io.trino.operator.PageBufferClientStatus
io.trino.operator.PartitionedOutputOperator$PartitionedOutputInfo
io.trino.operator.SplitOperatorInfo
io.trino.operator.TableFinishInfo
io.trino.operator.TableWriterOperator$TableWriterInfo
io.trino.operator.WindowInfo
io.trino.operator.WindowInfo$DriverWindowInfo
io.trino.operator.exchange.LocalExchangeBufferInfo
io.trino.sql.planner.plan.StatisticsWriterNode$WriteStatisticsHandle
io.trino.sql.planner.plan.TableWriterNode$CreateTarget
io.trino.sql.planner.plan.TableWriterNode$InsertTarget
io.trino.sql.planner.plan.TableWriterNode$RefreshMaterializedViewTarget
53 changes: 53 additions & 0 deletions modelgen/java-extractor/config/roots-483.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Trino REST API root model
# Fully qualified class name

io.trino.client.QueryResults
io.trino.execution.QueryInfo
io.trino.server.BasicQueryInfo

io.trino.sql.planner.plan.OutputNode
io.trino.sql.planner.plan.ProjectNode
io.trino.sql.planner.plan.TableScanNode
io.trino.sql.planner.plan.ValuesNode
io.trino.sql.planner.plan.AggregationNode
io.trino.sql.planner.plan.MarkDistinctNode
io.trino.sql.planner.plan.FilterNode
io.trino.sql.planner.plan.WindowNode
io.trino.sql.planner.plan.RowNumberNode
io.trino.sql.planner.plan.LimitNode
io.trino.sql.planner.plan.DistinctLimitNode
io.trino.sql.planner.plan.TopNNode
io.trino.sql.planner.plan.SampleNode
io.trino.sql.planner.plan.SortNode
io.trino.sql.planner.plan.RemoteSourceNode
io.trino.sql.planner.plan.JoinNode
io.trino.sql.planner.plan.SemiJoinNode
io.trino.sql.planner.plan.SpatialJoinNode
io.trino.sql.planner.plan.IndexJoinNode
io.trino.sql.planner.plan.IndexSourceNode
io.trino.sql.planner.plan.TableWriterNode
io.trino.sql.planner.plan.TableFinishNode
io.trino.sql.planner.plan.UnnestNode
io.trino.sql.planner.plan.ExchangeNode
io.trino.sql.planner.plan.UnionNode
io.trino.sql.planner.plan.IntersectNode
io.trino.sql.planner.plan.EnforceSingleRowNode
io.trino.sql.planner.plan.GroupIdNode
io.trino.sql.planner.plan.ExplainAnalyzeNode
io.trino.sql.planner.plan.ApplyNode
io.trino.sql.planner.plan.AssignUniqueId
io.trino.sql.planner.plan.CorrelatedJoinNode
io.trino.sql.planner.plan.StatisticsWriterNode
io.trino.metadata.AnalyzeTableHandle
io.trino.metadata.InsertTableHandle
io.trino.metadata.OutputTableHandle
io.trino.operator.PageBufferClientStatus
io.trino.operator.TableFinishInfo
io.trino.operator.TableWriterOperator$TableWriterInfo
io.trino.operator.WindowInfo
io.trino.operator.WindowInfo$DriverWindowInfo
io.trino.operator.exchange.LocalExchangeBufferInfo
io.trino.sql.planner.plan.StatisticsWriterNode$WriteStatisticsHandle
io.trino.sql.planner.plan.TableWriterNode$CreateTarget
io.trino.sql.planner.plan.TableWriterNode$InsertTarget
io.trino.sql.planner.plan.TableWriterNode$RefreshMaterializedViewTarget
Loading
Loading