Module: ClickhouseRuby::Types::StringParser

Defined in:
lib/clickhouse_ruby/types/string_parser.rb

Overview

Shared utilities for parsing ClickHouse string representations of complex types (arrays, tuples, maps)

These methods handle the common patterns of parsing nested structures with proper handling of quotes, escape characters, and bracket depth.

Class Method Summary collapse

Class Method Details

.extract_bracketed(str, open_bracket, close_bracket) ⇒ String

Validates and extracts content from a bracketed string

Examples:

StringParser.extract_bracketed("[1, 2, 3]", "[", "]")
# => "1, 2, 3"

Parameters:

  • str (String)

    bracketed string like “[…]” or “(…)”

  • open_bracket (String)

    expected opening bracket

  • close_bracket (String)

    expected closing bracket

Returns:

  • (String)

    inner content (may be empty)

Raises:

  • (ArgumentError)

    if format is invalid



107
108
109
110
111
112
113
114
# File 'lib/clickhouse_ruby/types/string_parser.rb', line 107

def extract_bracketed(str, open_bracket, close_bracket)
  str = str.strip
  unless str.start_with?(open_bracket) && str.end_with?(close_bracket) && str.length >= 2
    raise ArgumentError, "Expected #{open_bracket}...#{close_bracket} format, got: '#{str}'"
  end

  str[1...-1]
end

.parse_and_unquote(str, open_brackets: ["[", "(", "{"], close_brackets: ["]", ")", "}"]) ⇒ Array<String>

Parses elements and unquotes them in one step

Parameters:

  • str (String)

    the string to parse

  • open_brackets (Array<String>) (defaults to: ["[", "(", "{"])

    characters that increase nesting depth

  • close_brackets (Array<String>) (defaults to: ["]", ")", "}"])

    characters that decrease nesting depth

Returns:



123
124
125
126
127
128
129
130
131
132
# File 'lib/clickhouse_ruby/types/string_parser.rb', line 123

def parse_and_unquote(str, open_brackets: ["[", "(", "{"], close_brackets: ["]", ")", "}"])
  parse_delimited(str, open_brackets: open_brackets, close_brackets: close_brackets).map do |el|
    # Only unquote simple quoted strings, preserve nested structures
    if el.start_with?("'") && el.end_with?("'") && !el.include?("[") && !el.include?("(") && !el.include?("{")
      unquote(el)
    else
      el
    end
  end
end

.parse_delimited(str, open_brackets: ["[", "(", "{"], close_brackets: ["]", ")", "}"]) ⇒ Array<String>

Parses a comma-separated list of elements, respecting nested structures and quotes

Examples:

StringParser.parse_delimited("a, b, c")
# => ["a", "b", "c"]

StringParser.parse_delimited("'hello', [1, 2], 'world'")
# => ["'hello'", "[1, 2]", "'world'"]

Parameters:

  • str (String)

    the string to parse

  • open_brackets (Array<String>) (defaults to: ["[", "(", "{"])

    characters that increase nesting depth

  • close_brackets (Array<String>) (defaults to: ["]", ")", "}"])

    characters that decrease nesting depth

Returns:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/clickhouse_ruby/types/string_parser.rb', line 28

def parse_delimited(str, open_brackets: ["[", "(", "{"], close_brackets: ["]", ")", "}"])
  elements = []
  current = +""
  depth = 0
  in_string = false
  escape_next = false

  str.each_char do |char|
    if escape_next
      current << char
      escape_next = false
      next
    end

    case char
    when "\\"
      escape_next = true
      current << char
    when "'"
      in_string = !in_string
      current << char
    when *open_brackets
      depth += 1 unless in_string
      current << char
    when *close_brackets
      depth -= 1 unless in_string
      current << char
    when ","
      if depth.zero? && !in_string
        elements << current.strip
        current = +""
      else
        current << char
      end
    else
      current << char
    end
  end

  elements << current.strip unless current.strip.empty?
  elements
end

.unquote(str) ⇒ String

Removes surrounding single quotes and unescapes content

Examples:

StringParser.unquote("'hello'")
# => "hello"

StringParser.unquote("'it\\'s'")
# => "it's"

StringParser.unquote("123")
# => "123"

Parameters:

  • str (String)

    potentially quoted string

Returns:

  • (String)

    unquoted string with escapes processed



86
87
88
89
90
91
92
93
# File 'lib/clickhouse_ruby/types/string_parser.rb', line 86

def unquote(str)
  str = str.strip
  if str.start_with?("'") && str.end_with?("'") && str.length >= 2
    str[1...-1].gsub("\\'", "'")
  else
    str
  end
end