Class: OvertureMaps::QueryEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/overture_maps/query_engine.rb

Overview

Runs spatial SQL against Overture GeoParquet via DuckDB.

Prefers the ruby-duckdb gem (in-process, bound parameters, no shell). Falls back to the DuckDB CLI: PATH lookup first, then a verified download. All user-supplied values go through bound parameters (native) or strict literal quoting (CLI) — never raw string interpolation.

Defined Under Namespace

Classes: Error

Constant Summary collapse

DUCKDB_CLI_VERSION =
"1.5.3"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.cli_available?Boolean

Returns:

  • (Boolean)


215
216
217
218
# File 'lib/overture_maps/query_engine.rb', line 215

def cli_available?
  !!(OvertureMaps.configuration.duckdb_cli_path || find_in_path("duckdb") ||
     File.executable?(cached_cli_path))
end

.cli_pathObject

Resolve the DuckDB CLI: configured path, PATH, cached download — downloading a pinned release if necessary.



201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/overture_maps/query_engine.rb', line 201

def cli_path
  configured = OvertureMaps.configuration.duckdb_cli_path
  return configured if configured && File.executable?(configured)

  found = find_in_path("duckdb")
  return found if found

  cached = cached_cli_path
  return cached if File.executable?(cached)

  download_cli(cached)
  cached
end

.instanceObject



20
21
22
# File 'lib/overture_maps/query_engine.rb', line 20

def instance
  @instance ||= new
end

.reset!Object



24
25
26
# File 'lib/overture_maps/query_engine.rb', line 24

def reset!
  @instance = nil
end

Instance Method Details

#copy_to(sql, params: [], output_path:, format: "parquet") ⇒ Object

Exports a query's results to a local file (parquet by default). This is the bulk-data path: DuckDB streams row groups from S3 and writes the file without materializing results in Ruby.



42
43
44
45
46
47
48
49
50
51
# File 'lib/overture_maps/query_engine.rb', line 42

def copy_to(sql, params: [], output_path:, format: "parquet")
  copy_sql = build_copy_sql(sql, output_path, format)

  if native?
    native_execute(copy_sql, params)
  else
    cli_execute(interpolate(copy_sql, params))
  end
  output_path
end

#native?Boolean

Returns:

  • (Boolean)


53
54
55
56
57
58
59
60
61
62
63
# File 'lib/overture_maps/query_engine.rb', line 53

def native?
  return @native unless @native.nil?

  @native =
    begin
      require "duckdb"
      true
    rescue LoadError
      false
    end
end

#query(sql, params = []) ⇒ Object

Returns an array of row hashes. Intended for modest result sets (division searches, lookups) — bulk data must use #copy_to.



31
32
33
34
35
36
37
# File 'lib/overture_maps/query_engine.rb', line 31

def query(sql, params = [])
  if native?
    native_query(sql, params)
  else
    cli_query(sql, params)
  end
end