How to use placeholders in JSON (RedBeanPHP)? - sql

I have a task: to check if $username has upvoted the record with the identifier $id. To do this, I need to check that in the JSON array, which is in the "votes" cell, the "upvote" field contains the username (i.e. $username). So I wrote this code (PostgreSQL DB):
$foo = R::getRow('SELECT "votes"::jsonb #> \'{"upvote":[":username"]}\'::jsonb AS "is_upvoted" FROM "pages" WHERE "id" = :id', [":id"=>$id,":username"=>$username];
The problem is that RedBeanPHP, when substituting placeholders, wraps them in single brackets, but PostgreSQL requires me to wrap the names of fields / values ​​of a JSON array in double quotes.
So how can I make it so that RB does not wrap placeholders with single quotes? Or how to make placeholders wrap with double quotes?

There was no need to compose JSON manually and fill in placeholders in it via RB.
It was necessary to create an array with the structure of the required JSON, and use a ready-made array / variable to fill it.
Here's how I did it:
$username_in_array = array('upvote' => array($username));
$username_in_json = json_encode($username_in_array);
$is_upvoted = R::getRow('SELECT "votes"::jsonb #> :username::jsonb AS "is_upvoted" FROM "pages" WHERE "id" = :id', [":id"=>$id,":username"=>$username_in_json];
The request takes the following form:
SELECT "votes"::jsonb #> '{"upvote":["admin"]}'::jsonb AS "is_upvoted" FROM "pages" WHERE "id" = 1
I checked - it works!

Related

how to store special characters in json column in mysql

Im am trying to save some special characters in a json column of a table. but this is actually not working
this is how it is stored
{"district":"\u099a\u09be\u0981\u09a6\u09aa\u09c1\u09b0",
"sub_district":"\u099a\u09be\u0981\u09a6\u09aa\u09c1\u09b0"}
i am storing my input values as below..i am using laravel
present = array('district'=>$request->district,'sub_district'=>$request->sub_districtce);
$card->present_address = json_encode($present);
and while searching for a string in that json object, i am using a query below
$allowances = Card::SELECT('id','name','nid','village')
->where(DB::raw("json_extract((present_address), '$.district')"), চাদপুর)
->get();
can anybody help me on this situation where i can store special characters/unicodes in that json object.?
It is perfectly normal. As soon as you will do json_decode(), you will get back your expected values:
array (
'district' => 'চাঁদপুর',
'sub_district' => 'চাঁদপুর',
)

Ruby array as parameter to a plain SQL Query

I'm building a command line application that needs to connect in various postgresql databases and execute different queries in the ones as Prepared Statements. In a specific query, I need to use the IN clause in conjunction with the ActiveRecord's connection_raw method. My code is so:
ActiveRecord::Base.connection_raw.prepare('read_publications', "UPDATE publications SET readed = TRUE WHERE id IN ($1);")
After, I try execute this query:
ActiveRecord::Base.connection_raw.exec_prepared('read_publications', [1,2,3,4])
The problem is this is not working. The following error is raised when the query runs:
no implicit conversion of Array into Integer
What I'm doing wrong? Exists a way in that I can convert this array to a value that the IN clause can understand?
If you are using a raw connection, you can't pass in arrays like you can with ActiveRecords. ActiveRecord does some preprocessing for you. If you need raw SQL, then you need a parameter for each array element.
arr = [1,2,3,4]
i = 1
param = []
arr.each { param.push(i); i+=1; }
sql = "UPDATE publications SET readed = TRUE WHERE id IN ($"+param.join(',$')+");"
ActiveRecord::Base.connection_raw.prepare('read_publications', sql)
ActiveRecord::Base.connection_raw.exec_prepared('read_publications', arr)
However, the documentation says the array parameters has to be in a certain format:
https://deveiate.org/code/pg/PG/Connection.html#method-i-exec_prepared
params is an array of the optional bind parameters for the SQL query. Each element of the params array may be either:
a hash of the form:
{:value => String (value of bind parameter)
:format => Fixnum (0 for text, 1 for binary)
}
See similar question: Prepare and execute statements with ActiveRecord using PostgreSQL

ruby variable inside sql statement

I am trying to use a ruby variable inside an sql statement. The following code works and deletes the second record of the templates table. How do i replace this number with my user defined variable "deleteid"?
deleteid = gets.chomp
$db.execute %q{DELETE FROM templates
WHERE id = 2}
You can use string interpolation:
$db.execute %{DELETE FROM templates WHERE id = #{deleteid}}
$db.execute %Q{DELETE FROM templates WHERE id = #{deleteid}}
UPDATE
User can pass arbitrary string. Using deleteid directly can be dangerous. As #muistooshort commented, you should escape the deleteid.
Consult your db driver's documentation for methods that accepts parameter and escape the parameter (or prepare method).
For example, if you use sqlite3-ruby, you can use Database#query, which will escape for you.
$db.prepare(%q{DELETE FROM templates WHERE id = ?}, [deleteid])
in pg, use Connection#exec_params:
$db.exec_params(%q{DELETE FROM templates WHERE id = $1}, [deleteid])

SQL: Use a predefined list in the where clause

Here is an example of what I am trying to do:
def famlist = selection.getUnique('Family_code')
... Where “””...
and testedWaferPass.family_code in $famlist
“””...
famlist is a list of objects
‘selection’ will change every run, so the list is always changing.
I want to return only columns from my SQL search where the row is found in the list that I have created.
I realize it is supposed to look like: in ('foo','bar')
But no matter what I do, my list will not get like that. So I have to turn my list into a string?
('\${famlist.join("', '")}')
Ive tried the above, idk. Wasn’t working for me. Just thought I would throw that in there. Would love some suggestions. Thanks.
I am willing to bet there is a Groovier way to implement this than shown below - but this works. Here's the important part of my sample script. nameList original contains the string names. Need to quote each entry in the list, then string the [ and ] from the toString result. I tried passing as prepared statement but for that you need to dynamically create the string for the ? for each element in the list. This quick-hack doesn't use a prepared statement.
def nameList = ['Reports', 'Customer', 'Associates']
def nameListString = nameList.collect{"'${it}'"}.toString().substring(1)
nameListString = nameListString.substring(0, nameListString.length()-1)
String stmt = "select * from action_group_i18n where name in ( $nameListString)"
db.eachRow( stmt ) { row ->
println "$row.action_group_id, $row.language, $row.name"
}
Hope this helps!

Parameterized DeleteAllByAttributes Doesn't Work in YII

I am using the following code:
MyClass::model()->deleteAllByAttributes(array('phone_number'=>':phone_number'), '', array(':phone_number'=>$phoneNumber));
And I am getting the following error:
CDbException
SQLSTATE[HY093]: Invalid parameter number: number of bound variables
does not match number of tokens. The SQL statement executed was:
DELETE FROM `my_class` WHERE `my_class`.`phone_number`=:yp0
(E:\xampp\htdocs\yii\db\CDbCommand.php:354)
I believe you don't need to bind the attributes in the attributes array (as in findAllByAttributes() too). The values in the params array are bound to values in the condition string, not the attributes array, so I believe the following should work for you (and be sanitized):
MyClass::model()->deleteAllByAttributes(array(
'phone_number'=>$phoneNumber,
));
Alternatively, you could use:
MyClass::model()->deleteAllByAttributes(array(),'`phone_number` = :phone_number',array(
':phone_number'=>$phoneNumber,
));
Which would have the same effect... But then you might as well use deleteAll():
MyClass::model()->deleteAll('`phone_number` = :phone_number',array(
':phone_number'=>$phoneNumber,
));