このコミットが含まれているのは:
2026-10-28 20:34:11 +09:00
コミット cb3f4c600a
14個のファイルの変更、208行の追加、33行の削除
+11 -1
ファイルの表示
@@ -30,10 +30,11 @@ class CountsCondition
nullable = prefix.present? || (physical ? physical[:nullable] : key != 'latest')
nullable = false if field[:children]
entry = { key:, type:, labels: path_labels, nullable:,
multiple: prefix.present? || field[:children].present?,
multiple: prefix.present? || field[:children].present? || field[:multiple_values],
collection: field[:children].present? || type == :interval,
operators: CountsResourceDefinition::OPERATORS.fetch(type) }
entry[:label_values] = field[:label_values] if field[:label_values]
entry[:name_locale] = field[:name_locale] if field[:name_locale]
result.reject! { _1[:key] == key }
result << entry
visit.call(field[:children] || [], key, path_labels)
@@ -344,6 +345,7 @@ class CountsCondition
def source_for(key)
root, *parts = key.split('.')
if @definition.resource == 'tags' && @definition.name_column(root)
return @definition.alias_source(root) if root.start_with?('aliases_')
return [nil, @definition.name_expression(root)]
end
return [nil, "(#{ @population.latest_sql })"] if root == 'latest'
@@ -357,6 +359,10 @@ class CountsCondition
if root == 'parents'
source, id = parent_source
if @definition.resource == 'tags' && @definition.name_column(parts.first)
if parts.first.start_with?('aliases_')
aliases, value = @definition.alias_source(parts.first, 'parent_version')
return ["#{ source } JOIN #{ aliases }", value]
end
return [source, @definition.name_expression(parts.first, 'parent_version')]
end
if parts.first == 'names'
@@ -402,6 +408,10 @@ class CountsCondition
source = post_tag_source
document = 'tag_snapshot.item'
if @definition.name_column(parts.first)
if parts.first.start_with?('aliases_')
aliases, value = @definition.alias_source(parts.first, 'referenced_tag')
return ["#{ source } JOIN #{ aliases }", value]
end
return [source, @definition.name_expression(parts.first, 'referenced_tag')]
end
case parts.first
+8 -3
ファイルの表示
@@ -14,12 +14,17 @@ class CountsDefaults
details = detail_params(resource)
if details
name = CountsResourceDefinition.name_key(locale)
aliases = CountsResourceDefinition.aliases_key(locale)
details = details.transform_values do |value|
value.split(' ').map do |token|
value.split(' ').flat_map do |token|
if resource == 'tags' && ['name', 'parents.name'].include?(token)
token == 'name' ? name : "parents.#{ name }"
token == 'name' ? name : ["parents.#{ name }", "parents.#{ aliases }"]
elsif resource == 'tags' && token == 'aliases'
aliases
elsif resource == 'tags' && token.start_with?('aliases.')
[]
elsif resource == 'posts' && token == 'tags.name'
"tags.#{ name }"
["tags.#{ name }", "tags.#{ aliases }"]
else token
end
end.join(' ')
+6
ファイルの表示
@@ -139,6 +139,7 @@ class CountsExportProjection
if @complete_names && ((!@summary && @resource == 'tags') || row.key?(:names))
result['names'] = row[:names] || []
end
result['aliases'] = row[:aliases] if @complete_names && row.key?(:aliases)
result
end
@@ -155,6 +156,9 @@ class CountsExportProjection
end
def csv_display(value, key)
if key.start_with?('aliases_') && value.is_a?(Array)
return value.map { fetch(_1, 'name') }.compact.join("\n")
end
return @labels.fetch('bot', '') if key == 'created_by_user' && value.nil?
return @labels.fetch("event_type:#{ value }", value) if key == 'event_type'
return value ? @labels.fetch('latest', 'true') : '' if key == 'latest'
@@ -272,6 +276,8 @@ class CountsExportProjection
end
if @complete_names && ['tags', 'parents'].include?(prefix)
result['names'] = fetch(row, 'names') || []
aliases = fetch(row, 'aliases')
result['aliases'] = aliases if aliases
end
result
end
+34 -7
ファイルの表示
@@ -112,19 +112,29 @@ class CountsResourceDefinition
def field_label(key) = LABELS.fetch(key, "counts:attributes.#{ key }")
def self.name_key(code) = "name_#{ code.to_s.downcase.tr('-', '_') }"
def self.aliases_key(code) = "aliases_#{ code.to_s.downcase.tr('-', '_') }"
def name_columns
@name_columns ||= Locale.order(:code).map do |locale|
{ key: self.class.name_key(locale.code), label: 'counts:localeName',
label_values: { locale: locale.name },
name_locale: { code: locale.code, language_code: locale.language_code,
script_code: locale.script_code } }
@name_columns ||= Locale.select(:code, :language_code, :script_code).order(:code)
.flat_map do |locale|
codes = { code: locale.code, language_code: locale.language_code,
script_code: locale.script_code }
[{ key: self.class.name_key(locale.code), label: 'counts:localeName', name_locale: codes },
{ key: self.class.aliases_key(locale.code), label: 'counts:localeAliases',
name_locale: codes, multiple_values: true }]
end
end
def name_column(key) = name_columns.find { _1[:key] == key }
def name_expression(key, row = 'v')
if key.start_with?('aliases_')
source, value = alias_source(key, row)
return "CAST(COALESCE((SELECT JSON_ARRAYAGG(#{ value }) OVER (" +
'ORDER BY locale_alias.ordinal ROWS BETWEEN UNBOUNDED PRECEDING ' +
"AND UNBOUNDED FOLLOWING) FROM #{ source } WHERE #{ value } IS NOT NULL " +
'LIMIT 1), JSON_ARRAY()) AS CHAR) COLLATE utf8mb4_bin'
end
locale = name_column(key).fetch(:name_locale)
connection = model.connection
path = connection.quote("$.#{ locale[:language_code].to_json }")
@@ -135,6 +145,19 @@ class CountsResourceDefinition
"CONCAT(#{ path }, '.name')), CAST('null' AS JSON))) END"
end
def alias_source(key, row = 'v')
locale = name_column(key).fetch(:name_locale)
connection = model.connection
path = connection.quote("$.#{ locale[:language_code].to_json }.aliases[*]")
script = connection.quote(locale[:script_code])
source = "JSON_TABLE(COALESCE(#{ row }.names, JSON_OBJECT()), #{ path } " +
"COLUMNS (ordinal FOR ORDINALITY, name TEXT PATH '$.name', " +
"script TEXT PATH '$.script_code')) locale_alias"
value = "CASE WHEN LOWER(locale_alias.script) = LOWER(#{ script }) " +
'THEN locale_alias.name END'
[source, value]
end
def output_fields
content = case resource
when 'posts'
@@ -149,6 +172,7 @@ class CountsResourceDefinition
keys.flat_map do |key|
next name_columns if key == 'name' && resource == 'tags'
next [] if key == 'names' && resource == 'tags'
next [] if key == 'aliases' && resource == 'tags'
label = if key == 'parents'
resource == 'tags' ? 'tags:parents' : 'shared:labels.parentPosts'
else field_label(key)
@@ -174,6 +198,7 @@ class CountsResourceDefinition
else []
end
keys.flat_map do |child|
next [] if child == 'aliases' && key == 'tags'
if child == 'name' && ['tags', 'parents'].include?(key)
next [{ key: child, label: CHILD_LABELS.fetch(child) }, *name_columns]
end
@@ -194,14 +219,16 @@ class CountsResourceDefinition
fields = output_fields
if resource == 'tags'
fields += [{ key: 'name', label: 'counts:columns.name' },
{ key: 'names', label: 'counts:columns.names', children: child_fields('names') }]
{ key: 'names', label: 'counts:columns.names', children: child_fields('names') },
{ key: 'aliases', label: 'tags:aliases', children: child_fields('aliases') }]
end
if resource == 'posts'
fields = fields.map do |field|
next field unless field[:key] == 'tags'
field.merge(children: field[:children] + [
{ key: 'names', label: 'counts:columns.names', children: child_fields('names') }])
{ key: 'names', label: 'counts:columns.names', children: child_fields('names') },
{ key: 'aliases', label: 'tags:aliases', children: child_fields('aliases') }])
end
end
fields