Using Ruby and SQL SMO for Script Automation - ruby

I need to create a script in ruby to get all the database objects (tables,views,sps, functions, etc) and be able to create files for each of the db objects.
I would like to be able to implement this solution in ruby and use some sort of Win32 class may be?.
I am using SQL Server 2008 R2. Not ruby on rails of course.

# == Name
# SQL Server Library
# == Author
# Maverick
# == Synopsis
# ADO SQL Server Library
# == Notes:
# Modify the following global variables in order to set up an execution environment
# sql_str: This is the SQL CMD command option and arguments -> Change the -U and -P arguments for -E to enable integrated security
# http://rubyonwindows.blogspot.com/2007/03/ruby-ado-and-sqlserver.html
Thread.abort_on_exception = true
require 'win32ole'
require 'win32api'
CoInitialize = Win32API.new('ole32', 'CoInitialize', 'P', 'L')
# This class manages database connection and queries
class SqlServer
attr_accessor :connection, :data, :fields
def initialize
#connection = nil
#data = nil
#cmd_time_out = 900
end
#opens a database connection using integrated security
def open(server,database)
connection_string = "Provider=SQLOLEDB.1;"
connection_string << "Persist Security Info=False;"
connection_string << "Integrated Security=SSPI;"
connection_string << "Initial Catalog=#{database};"
connection_string << "Data Source=#{server};"
connection_string << "Network Library=dbmssocn"
CoInitialize.call( 0 )
if server.eql?(nil) or database.eql?(nil) or server.eql?('') or database.eql?('') then
raise Exception, "Application Error: Server or Database parameters are missing"
end
begin
#connection = WIN32OLE.new('ADODB.Connection')
#connection.ConnectionString = connection_string
#connection.open
rescue Exception => e
#connection.Errors.Count.times { |x|
show_ado_error(#connection.Errors)
}
raise Exception, "Application Error: #{e.message} \n Can't open a connection with the server. Verify user credentials"
end
end
def get_connection
return #connection
end
#executes a query without returning any rows
def execute_non_query(query)
begin
command = WIN32OLE.new('ADODB.Command')
command.CommandType = 1
command.ActiveConnection = #connection
command.CommandText = query
command.CommandTimeOut = #cmd_time_out
result = command.Execute
if #connection.Errors.Count > 1 then
raise Exception,"ADODB Connection contains errors"
end
rescue Exception => e
show_ado_error(#connection.Errors)
raise Exception, "Application Error: #{e.message} \n Can't execute query. Verify sql syntax"
end
return result
end
#prints ado db errors using ado connection error property
def show_ado_error(obj)
obj.Count.times { |x|
puts "#{x}. ADODB Error Number: " + #connection.Errors(x).Number.to_s
puts "#{x}. ADODB Generated By: " + #connection.Errors(x).Source
puts "#{x}. ADODB SQL State: " + #connection.Errors(x).SQLState
puts "#{x}. ADODB Native Error: " + #connection.Errors(x).NativeError.to_s
puts "#{x}. ADODB Description: " + #connection.Errors(x).Description
}
end
#executes a query returning an array of rows
def execute_query(sql_query)
# Create an instance of an ADO Record set
begin
record_set = WIN32OLE.new('ADODB.Recordset')
# Open the record set, using an SQL statement and the
# existing ADO connection
record_set.open(sql_query, #connection)
# Create and populate an array of field names
#fields = []
record_set.fields.each do |field|
#fields << field.Name
end
begin
# Move to the first record/row, if any exist
record_set.movefirst
# Grab all records
#data = record_set.getrows
rescue
#data = []
end
record_set.close
# An ADO Recordset's GetRows method returns an array
# of columns, so we'll use the transpose method to
# convert it to an array of rows
#data = #data.transpose
rescue
raise Exception, "Application Error: Can't execute query. Verify SQL Query syntax"
end
end
def close
#connection.Close
end
end

Related

sqlite3 .execute2 snagging in a ruby file

I have the following sqlite code as a standalone file. It works.
the schema is basic. foo.db table bar Id, Text, Value, Etc are my columns
#!/usr/bin/env ruby
require 'sqlite3'
puts "enter a number"
input = gets.chomp.to_i
begin
db = SQLite3::Database.open('foo.db')
find_data = db.execute2 "select * from bar where Value = #{input}"
find_data.each do |f|
puts "[%-8s] %-8s | %-8s" % [f[1], f[2], f[3]]
end
rescue SQLite::Exception => e
puts e
ensure
db.close if db
end
execute2 locates the line and find_data.each prints out.
However when I take the above snippet and place into a method in a larger program, I get `no such column: [input]"
In my method. I have condensed the code:
...
def find_info(info)
begin
db = SQLite3::Database.open('foo.db')
puts db.get_first_value "select SQLite_VERSION()"
return "create a directory first" unless File.exist?('foo.db')
#line below does not work at print_out below
print_out = db.execute2 "SELECT * FROM Bar WHERE Value=#{info}"
#but making the following changes works:
#info_in = info; print_out = db.execute2 "select * from BAR WHERE Value = :info_in", info_in
return "no match" unless print_out != nil
print_out.each do |line|
puts "[%-8s] %-8s | %-8s" % [line[1], line[2], line[3]]
end
rescue SQLite3::Exception => e
puts e
ensure
db.close if db
end
end
...
print 'enter text to search for'
info = gets.chomp.to_s
X.NewInstance.new; X.find_info(info)
My question: Why am I obligated to use a placeholder in print_out? I believe I should be able just throw in a variable as print_out = db.execute2 "select * from Bar WHERE Value=#{info}"
please help. I am dumbfounded.
(Also: there must be a way on SO to indent blocks of code most efficiently than hitting 4 spaces for each line of code...I spend more time formatting the code than I do typing the question...pls advise?)
String interpolation fails in this instance. Placeholders can be utilized.
print_out = db.execute2 "select * from BAR WHERE Value = :info", info
print_out.each do |p|
puts "%s %s %s" % [p[1],p[2],p[3]]
end

Create and Edit reg key in Ruby

I am trying to create and edit a reg key in ruby but keep getting the following error:
setKeyStringValue error:
false
error in 'open' system cannot find file specified
My code:
require 'win32/registry'
$hkey_local_machine=Win32::Registry::HKEY_LOCAL_MACHINE
$hkey_current_user=Win32::Registry::HKEY_CURRENT_USER
# Returns the Microsoft Registry path to the Microsoft software information
def getKeyValue(hive, key_path, key_name)
reg_obj=hive.open(key_path, Win32::Registry::KEY_READ)
begin
reg_typ, reg_val = reg_obj.read(key_name)
rescue Win32::Registry::Error
puts "key not found : #{key_name}"
end
return reg_val
end
#used to set a String value for a key
def setKeyStringValue(hive,key_path, key_name, key_value)
begin
reg_key=hive.open(key_path, Win32::Registry::KEY_WRITE)
puts "opened key"
reg_key.write(key_name,Win32::Registry::REG_SZ,key_value)
rescue Win32::Registry::Error
puts "setKeyStringValue error:"
return false
end
return true
end
puts setKeyStringValue(Win32::Registry::HKEY_CURRENT_USER,"SOFTWARE\\PsychSoft","foo","woo")
puts getKeyValue(Win32::Registry::HKEY_CURRENT_USER,"SOFTWARE\\PsychSoft","foo")
Can someone explain why this code doesnt work?
I suppose your registry path needs to be enclosed in single '
Your code works like this
profiles_key = 'Software\Microsoft'
puts setKeyStringValue(Win32::Registry::HKEY_CURRENT_USER, profiles_key, "foo", "woo")
puts getKeyValue(Win32::Registry::HKEY_CURRENT_USER, profiles_key, "foo")
Which gives
opened key
true
woo

What causes the error "undefined local variable or method `csv' for main:Object"?

I am trying to write a rake task for importing a CSV file into multiple models. The code compiles without error, but I get this error message when I attempt to run it:
rake aborted! NameError: undefined local variable or method csv' for
main:Object
/Users/rickcasey/Projects/Programming/wfrails/lib/tasks/import_partial.rake:28:in
block in '
Here is the script:
desc "Imports the CSV file "
task :import_partial => :environment do
require 'csv'
csv.foreach('public/partial.csv', :headers => true) do |row|
# create records in independent tables
# create the Company object
this_company_name = row.to_hash.slice(*%w[county_name])
if !(Company.exists?(company_name: this_company_name))
Companies.create(row.to_hash.slice(*%w[company_name operator_num]))
end
thecompany = Company.find(this_company_name)
company_id = thecompany.id
# create the County object
this_county_name = row.to_hash.slice(*%w[county])
if !(County.exists?(county_name: this_county_name))
Counties.create(county_name: this_county_name)
end
thecounty = County.find(this_county_name)
county_id = thecounty.id
# create the GasType object
this_gastype_name = row.to_hash.slice(*%w[gas_type])
if !(GasType.exists?(gastype_name: this_gastype_name))
GasType.create(gastype_name: this_gastype_name)
end
thegastype = GasType.find(this_gastype_name)
gastype_id = thegastype.id
# create the Field object
this_field_name = row.to_hash.slice(*%w[field])
if !(Field.exists?(field_name: this_field_name))
Field.create(field_name: this_field_name, field_code: field_code)
end
thefield = Field.find(this_field_name)
field_id = thefield.id
# create the Formations object
this_formation_name = row.to_hash.slice(*%w[formation])
if !(Formation.exists?(formation_name: this_formation_name))
Counties.create(formation: this_formation_name, formation_code: formation_code)
end
theformation = Formation.find(this_formation_name)
formation_id = theformation.id
# debugging:
puts "company_id:", company_id
puts "county_id:", county_id
puts "gastype_id:", gastype_id
puts "field_id:", field_id
puts "formation_id:", formation_id
# create records in dependent tables:
# Use the record id's from above independent table create records containing foreign keys:
#Facilities.create(row.to_hash.slice(*%w[dir_e_w dir_n_s dist_e_w dist_n_s facility_name facility_num ground_elev lat long meridian qtrqtr range sec twp utm_x utm_y])
#Wells.create(row.to_hash.slice(*%w[api_county_code api_seq_num first_prod_date form_status_date formation_status sidetrack_num spud_date status_date td_date test_date wbmeasdepth wbtvd well_bore_status well_name])
end
end
My environment is: ruby 2.1.2p95, Rails 4.1.1
This is quite unclear, and have not found an example of similar error with an answer I understand yet....any help much appreciated!
I believe the error is in this line
csv.foreach('public/partial.csv', :headers => true) do |row|
It should be
CSV.foreach('public/partial.csv', :headers => true) do |row|
I believe the class name is uppercase - CSV.foreach, not csv.foreach.

ruby sqlite error 'ensure in insert_row': undefined local variable or method 'stmt'

I have the following method in a dbmgr ruby class, which I'm using within a loop to insert data from a csv into a sqlite3 db:
def insert_row(aRow)
begin
#db = SQLite3::Database.open("#{#dbn}")
rhash = aRow.row_hash
stm = #db.prepare("INSERT INTO programs (programName, episodeName) VALUES (? , ? )")
stm.bind_param(1, '#{rhash["Program"]}' )
stm.bind_param(2, '#{rhash["Episode Name"]}' )
stmt.execute()
programId = #db.last_insert_row_id
rescue SQLite3::Exception => e
puts "Exception occured"
puts e.message
puts e.backtrace
ensure
stmt.close if stmt
#db.close if #db
end #db
When I do that on the console after the 1st insertion I get the following error:
`ensure in insert_row': undefined local variable or method `stmt' for #<Dbmgr:0x007f9511050188> (NameError)
Initially, I did not use the prepare and bind_params features of ruby for sqlite. However, after some characters like " ' " in the text I was inserting generated exceptions, I read somewhere that using bind_params would clean the input so I used bind_params. But now I'm getting this error.
stm = #db.prepare("INSERT INTO programs (programName, episodeName) VALUES (? , ? )")
stm.bind_param(1, '#{rhash["Program"]}' )
stm.bind_param(2, '#{rhash["Episode Name"]}' )
stmt.execute() # <-- you're referring to stmt instead of stm here
programId = #db.last_insert_row_id
You've used stm throughout this statement, then refer to stmt.execute() and stmt.close

Unable to get utf8 characters from SQL server in ruby cucumber automation

I'm using Ruby cucumber to automate my application. I'm using DSN ODBC driver and "dbi" to connect to my sql server 2012 DB. It is connected successfully and I can get the records. But when I'm trying to get unicode (utf-8) data from a table in ruby scripts, I get garbage characters (???????).
Please help me get unicode characters from DB.
Below is the code what I have used to connect and retrieve data from DB.
# encoding: UTF-8
require 'rubygems'
require 'DBI'
def run_select_query_verifyText(query,verifyString)
connection = nil
status = false
begin
#puts "Connecting to DataBase"
connection = DBI.connect('DBI:ODBC:ODBCDriver','test','xxxxx')
rescue DBI::DatabaseError => e
puts "An error occurred"
puts "Error code: #{e.err}"
puts "Error message: #{e.errstr}"
return false
end
#execute sql query
dataset = connection.execute(query)#.fetch_all
dataset.each do |row|
row.each do |data|
puts "cell data is #{data}"
if data == verifyString then
status = true
break
end
end
if status then
break
end
end
connection.disconnect
return status
end
I had similar issue, which is fixed with following line in env.rb file
ENV['CUCUMBER_OUTPUT_ENCODING'] = 'UFT-8'

Resources