#!/usr/bin/env ruby # A script to automatically generate SQL files from an interface definition. # To be called like this: sql-template-renderer interface.yaml sql-template.erb require 'yaml' require 'erb' class SqlTemplateRenderer DATASERVICES_CLIENT_SCHEMA = 'cdb_dataservices_client' DATASERVICES_SERVER_SCHEMA = 'cdb_dataservices_server' def initialize(template_file, function_signature) @function_signature = function_signature @template = File.read(template_file) end def render ERB.new(@template, _save_level=nil, _trim_mode='-').result(binding) end def name @function_signature['name'] end def return_type @function_signature['return_type'] end def requires_permission @function_signature['requires_permission'] end def permission_name @function_signature['permission_name'] end def permission_error @function_signature['permission_error'] end def multi_field @function_signature['multi_field'] end def multi_row @function_signature['multi_row'] end def user_config_key @function_signature['user_config_key'] end def geocoder_config_key @function_signature['geocoder_config_key'] end def parameters_info(with_user_org) parameters = [] if with_user_org parameters << { 'name' => 'username', 'type' => 'text' } parameters << { 'name' => 'orgname', 'type' => 'text' } end parameters + @function_signature['params'].reject(&:empty?) end def user_org_declaration() "username text;\n orgname text;" unless superuser_function? end def params(with_user_org = superuser_function?) parameters_info(with_user_org).map { |p| p['name'].to_s } end def params_with_type(with_user_org = superuser_function?) parameters_info(with_user_org).map { |p| "#{p['name']} #{p['type']}" } end def params_with_type_and_default(with_user_org = superuser_function?) parameters = parameters_info(with_user_org).map do |p| if not p['default'].nil? "#{p['name']} #{p['type']} DEFAULT #{p['default']}" else "#{p['name']} #{p['type']}" end end return parameters end def superuser_function? !!@function_signature['superuser'] end def void_return_type? return_type.downcase == 'void' end def return_declaration "ret #{return_type};" unless void_return_type? || multi_row end def return_statement(&block) if block erb_out = block.binding.eval('_erbout') if multi_row erb_out << 'RETURN QUERY SELECT * FROM ' elsif multi_field erb_out << 'SELECT * FROM ' elsif void_return_type? erb_out << 'PERFORM ' else erb_out << 'SELECT ' end yield if multi_row || void_return_type? erb_out << ';' else erb_out << ' INTO ret;' end if !multi_row && !void_return_type? erb_out << ' RETURN ret;' end else if !multi_row && !void_return_type? ' RETURN ret;' end end end end if ARGV.length != 2 then puts "Usage: sql-template-renderer " exit end interface_source_file = ARGV[0] template_file = ARGV[1] functions = YAML.load(File.open(interface_source_file)) functions.each do |f| puts SqlTemplateRenderer.new(template_file, f).render end