Inserting with multiple parameters gives SQLite3::RangeException - ruby

I'm using the Ruby Sqlite3 library to insert some records into a database. I'm having issues getting the statements below to work (I've tried all variants that are posted); I get a SQLite3::RangeException - bind or column index out of range: exception.
The query works if I just hardcode values into it... so what am I doing wrong?
statement = db.prepare("insert into IntegrationLogin (Username, Password, ProjectID) values (\"?1\", \"?2\", 1)")
statement.execute [params['username'], params['password']]
statement = db.prepare("insert into IntegrationLogin (Username, Password, ProjectID) values (\"?1\", \"?2\", 1)")
statement.execute params['username'], params['password']
statement = db.prepare("insert into IntegrationLogin (Username, Password, ProjectID) values (\"?\", \"?\", 1)")
statement.execute params['username'], params['password']

I think your problem lies with trying to encapsulate the parameter indicators (?) in quotes. This is unnecessary as the driver will wrap the string parameter in quotes and perform any additional escaping before executing the query. When I removed the quotes you example queries executed fine.
It looks like your superfluous quotations are escaping the parameter indicators somehow and the driver isn't seeing them.
Use this:
statement = db.prepare("insert into IntegrationLogin (Username, Password, ProjectID) values (?, ?, 1)")
You were making this harder than it needed to be. Don't worry, this kind of parameter binding completely prevents SQL injection, even without the extra quotes.

Related

Getting invalid identifier SQL query

I am trying to execute next query:
MERGE INTO NOTIFICATION_OBJS p
USING (SELECT
:fcsNotif_id as doc_id,
:OKPD2_code as OKPD2_code,
:OKPD2_name as OKPD2_name,
:quantity_value as quantity,
:purchaseObject_price as price
FROM DUAL
) v
ON (p.doc_id=v.doc_id)
WHEN MATCHED THEN
UPDATE SET
p.OKPD2_code = v.OKPD2_code,
p.OKPD2_name = v.OKPD2_name,
p.quantity_value = v.quantity_value,
p.price = v.price
WHEN NOT MATCHED THEN
INSERT (p.doc_id, p.OKPD2_code, p.OKPD2_name, p.quantity_value, p.price)
VALUES(v.doc_id, v.OKPD2_code, v.OKPD2_name, v.quantity_value, v.price)
I am sending to bind method next dictionary:
{'OKPD2_code': '62.02.30.000', 'OKPD2_name': 'some text', 'purchaseObject_price': '20466982.25', 'quantity_value': '1', 'fcsNotif_id': '18941152'}
But I am getting error:
ORA-00904: "P"."OKPD2_NAME": invalid identifier
All other query with binding are working. Please help me to find error.
There's no OKPD2_NAME column in NOTIFICATION_OBJS table.
If you used double quotes while creating that table (and its columns), you should
recreate the table without double quotes, or
reference the table (and its columns that use mixed case) using double quotes again, specifying case EXACTLY as it was while creating the table
[EDIT, after the screenshot has been uploaded]
Column name really is created using mixed case, so you'll have to reference it exactly like that: "OKPD2_name" paying attention to double quotes and mixed case.
If you use "okpd2_name" or "okPD2_NAME" or anything but "OKPD2_name", it won't work. Once again: get rid of double quotes.

Sqlite3 value in Ruby Script not working as string

I am trying to create a user-auth system and have run into a problem. In this code, I am trying to check if a certain value matches another value in the same row. It prints but does not work as a string when I set it equal to another string.
db.execute("CREATE TABLE IF NOT EXISTS auth(id int, name text, password text)")
db.execute("INSERT INTO auth(id, name, password) VALUES(?, ?, ?)", [1, 'Bugs', 'Carrots'])
t = db.execute("SELECT password FROM auth WHERE name = 'Bugs'")
if t == 'Carrots'
puts "yes"
end
#i am trying to print yes to the console
I think you're getting back an array representing the list of matches, although in this case there's only one row returned. Furthermore, the row itself is an array of values, although in this case the row will be an array of only one value. So you should be comparing t[0][0] rather than just t
You could use the function db.get_first_value instead to simplify this.
(This assumes that name is unique; you probably want to use a UNIQUE constraint in the database schema for both id and name.)
(And, yes, you should take #tadman's warning to heart.)
So here's a minimally altered version of the code you posted above (without the suggested improvements) that gives the desired result:
#!/usr/bin/env ruby
require 'sqlite3'
db = SQLite3::Database.new(':memory:')
db.execute("CREATE TABLE IF NOT EXISTS auth(id int, name text, password text)")
db.execute("INSERT INTO auth(id, name, password) VALUES(?, ?, ?)",
[1, 'Bugs', 'Carrots'])
t = db.execute("SELECT password FROM auth WHERE name = 'Bugs'")
if t[0][0] == 'Carrots'
puts "yes"
end

error using regexp_extract to extract a particular part of the string from Hive

I have a table with a column that has urls. I want to query out a particular url param value from each record. the url param can occur in any position in the url data and the url can contain hashbangs and this param can contain special chars like -, _ and |.
data table column:
url
http://www.url.com?like=hobby&name=tom-_green
http://www.url.com?name=bob|ghost&like=hobby
and I want the query results to be
name
srini
tom-_green
bob|ghost
I tried a query like
Select regexp_extract(url, '(?<=name=)[^&?]*(?:|$&)',2) as name
From table_name
I see java exceptions when I run this query. the exceptions are pretty vague and checking if someone can help.
I found another Hive implementation for handling URLs specifically..
Select parse_url(url, 'QUERY', 'name') as name From table_name and this worked :)
ref: parse_url(string urlString, string partToExtract [, string keyToExtract])
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF

writing basic Ruby code to register user in SQLite database

I need some help writing basic Ruby code to register a user in a SQLite database. I'm very new to Ruby, I checked lots of good examples online but my code still doesn't work.
This is my 1st test project using Ruby, so appreciate any help and apologise for making any bad mistakes.
require 'sqlite3'
def register_user(l)
user = l[1]
pass = l[2]
db = SQLite3::Database.new "database.db"
db.execute("INSERT INTO users (user, pass)
VALUES (#{user}, #{pass})")
end
def cmd_register(l)
if register_user(#{#nick}, l[1])
sv_send 'NOTICE', 'REGISTER', ':*** User created'
else
sv_send 'NOTICE', 'REGISTER', ':*** User not created'
end
end
There are a few problems with your code. First, here:
db.execute("INSERT INTO users (user, pass)
VALUES (#{user}, #{pass})")
You're trying to generate a query that looks like this (supposing the variable user contains "Jordan" and pass contains "xyz"):
INSERT INTO users (user, pass) VALUES('Jordan', 'xyz')
...but your code generates a query that looks like this:
INSERT INTO users (user, pass) VALUES(Jordan, xyz)
Do you see the difference? Values in SQL queries need to be surrounded by quotation marks. Your query will fail because SQLite doesn't know what Jordan is; it only knows what 'Jordan' is.
You could just add quotation marks to your query, but then you would have another problem: SQL injection attacks. Because you're just blindly putting the values of user and pass into your query, an attacker could manipulate those values to perform a different query than you intended. Never use string interpolation (#{var}) or concatenation (+ or <<) when creating an SQL query. (For a brief description of how SQL injection attacks work, read the "How to get hacked" section on this page: http://ruby.bastardsbook.com/chapters/sql/.)
The correct way to use variables in a query is with prepared statements and parameter binding. It looks like this:
statement = db.prepare("INSERT INTO users (user, pass) VALUES (?, ?)")
statement.bind_params(user, pass)
result = statement.execute
What this does is automatically escapes the values of user and pass to make sure they don't do anything you don't expect, wraps them in quotation marks, and substitutes them for the question marks in the query. Another way to do the same thing is this:
result = db.execute("INSERT INTO users (user, pass) VALUES (?, ?)", user, pass)
The other obvious problem with your code is this:
if register_user(#{#nick}, l[1])
This is a syntax error. You can only use the #{var} syntax in a string, like "hello #{var}". In this case you just want to do this:
if register_user(#nick, l[1])
require "sqlite3"
my_db = SQLite3::Database.new "my_db1.db"
my_db.execute <<END_OF_CREATE #The <<END_OF_CREATE .... END_OF_CREATE thing is called HEREDOC syntax, which is one way to create a String that spans multiple lines
CREATE TABLE IF NOT EXISTS users( #A useful SQL command to be aware of.
name varchar(30),
password varchar(30)
);
END_OF_CREATE
def register_user(target_db, user_info)
user_name, user_pass = user_info #A neat trick for "unpacking" an Array
target_db.execute(
"INSERT INTO users (name, password)
VALUES (?, ?)", user_name, user_pass #For security reasons, inserts into a db should use this "question mark" format.
)
end
register_user(my_db, ['John', 'abc123'])
register_user(my_db, ['Jane', 'xyz456'])
my_db.execute("SELECT * FROM users") do |row|
p row #Use the 'p' method instead of puts to print an Array or Hash.
end
--output:--
["John", "abc123"]
["Jane", "xyz456"]
Also, don't ever name a variable l. You absolutely, no exceptions, have to use descriptive variable names. See the code above for an example.
Even though the code above unpacks the user_info array into separate variables, that is actually not required because execute() will take an
Array as an argument:
target_db.execute(
"INSERT INTO users (name, password)
VALUES (?, ?)", user_info
)
In other words, all the values for the question marks can be gathered into an Array and provided as the last argument for execute().
One problem you can run into when writing and testing database programs is when you change one of the column names in your table. The code above will cause an error: the table will not be re-created because the table already exists, but your new code will use the new column name, which won't exist in the table.
So, you might consider using this combination of sql statements:
my_db.execute <<END_OF_DROP
DROP TABLE IF EXISTS users
END_OF_DROP
my_db.execute <<END_OF_CREATE
CREATE TABLE users(
name varchar(30),
password varchar(30)
);
END_OF_CREATE
With those sql statements, if you change one of the column names (or add a column), then your new code won't throw an error because the table is destroyed and recreated with the new column names every time you run your program.

Spring jdbcTemplate executing query

I have a strange problem ,
My Query looks like below.
String tokenQuery = "select id from table
where current_timestamp between
creation_time and (creation_time + interval '10' minute)
and token = '"+Token+"'";
But when I run, jdbcTemplate.queryForLong(tokenQuery) , no matter what , it always throws EmptyDataAccessException.
I am executing this in Oracle
Can we not append dynamic values to string and then pass it as a query and execute ?
What could be the issue ?
I assume that what you get is in fact an EmptyResultDataAccessException. The javadoc of this exception says:
Data access exception thrown when a result was expected to have at least one row (or element) but zero rows (or elements) were actually returned.
That simply means that the query is executed fine, and is supposed to return one row, but doesn't return any. So no row satisfies the criteria of your query.
If that is expected, then catch the exception, or use a method that returns a list rather then returning a single value. That way, you can test if the returned list is empty.
That said, you should use a parameterized query instead of concatenating the token like you're doing. This would prevent SQL injection attacks. It would also work even if the token contains a quote, for example.

Resources