I have a odd situation where I would like to phrase a variable inside an SQL string. Basically ODBC will return a query with a string, in that string there will be an Asterisk variable and I need that phrased and passed back to SQL. For example (pointless code but showing the example)-
exten => s,n,Set(QUERY=${ODBC_GET_QUERY(${EXTEN})})
The SQL query in func_odbc.conf is SELECT query FROM tablea WHERE number = ${ARG1}
Now QUERY will look like to = ${DIALED}, ${DIALED} being a asterisk variable (I will make it 17005551212 for example) I need that phrased so I end up with -
exten => s,n,Set(ALLOWED=${ODBC_GET_ALLOWED(${QUERY})})
The SQL query in func_odbc.conf would be SELECT allowed FROM tableb WHERE ${ARG1} so the SQL query would resolve to SELECT allowed WHERE to = 17005551212.
Before I dive into this and re-invent the wheel, is it possible or even allowed? I have actually not tried it yet. I know in a Set() statement it will phrase a variable inline, but is there a way to phrase variable that is in a variable when its returned via ODBC? Thanks!
Please read carefully source code.
Func odbc use prepair call. So it will not work for your example just becuase prepair do not allow do that.
In general you can substitute variables. Example 1 WILL work ok.
Workaround - use mysql EXEC.
Related
I would like to use update_all in order to update all records in a database.
Let me assume that the name of the attribute to be update is price.
I succeeded command A.
A
MyModel.update_all(price: "$500")
However, I would like to mysql function(e.g. IF, CONCAT, arithmetic...) in updating.
so I tried command B, but failed and the string value CONCAT('$', 500) was stored.
B
MyModel.update_all(price: "CONCAT('$', 500)")
I succeeded when I tried C, but I don't want use it because of the SQL injection risks.
C
MyModel.update_all("price = CONCAT('$', 500)")
How can I do that without any risk of SQL injection attacks?
Here, I have to use sql function here for some reasons.
Thank you in advance.
You need to create methods corresponding to allowable sql functions that take the params as input. So if you want to provide "CONCAT(..,...)" then user should be able to call a method like this. You can extent it to check type of arguments are allowed and add checks there as well.
def allowed_functions(func_name, all_args_here)
case func_name
when 'concat' then "CONCAT(#{all_args_here})"
end
end
I've written a common table expression to return hierarchical information and it seems to work without issue if I hard code a value into the WHERE statement. If I use a variable (even if the variable contains the same information as the hard coded value), I get the error The maximum recursion 100 has been exhausted before statement completion.
This is easier shown with a simple example (note, I haven't included the actual code for the CTE just to keep things clearer. If you think it's useful, I can certainly add it).
This Works
WITH Blder
AS
(-- CODE IS HERE )
SELECT
*
FROM Blder as b
WHERE b.PartNo = 'ABCDE';
This throws the Max Recursion Error
DECLARE #part CHAR(25);
SET #part = 'ABCDE'
WITH Blder
AS
(-- CODE IS HERE )
SELECT
*
FROM Blder as b
WHERE b.PartNo = #part;
Am I missing something silly? Or does the SQL engine handle hardcoded values and parameter values differently in this type of scenario?
Kindly put semicolon at the end of your variable assignment statement
SET #part ='ABCDE';
Your SELECT statement is written incorrectly: the SQL Server Query Optimizer is able to optimize away the potential cycle if fed the literal string, but not when it's fed a variable, which uses the plan that developed from the statistics.
SQL Server 2016 improved on the Query Optimizer, so if you could migrate your DB to SQL Server 2016 or newer, either with the DB compatibility level set to 130 or higher (for SQL Server 2016 and up), or have it kept at 100 (for SQL Server 2008) but with OPTION (USE HINT ('ENABLE_QUERY_OPTIMIZER_HOTFIXES')) added to the bottom of your SELECT statement, you should get the desired result without the max recursion error.
If you are stuck on SQL Server 2008, you could also add OPTION (RECOMPILE) to the bottom of your SELECT statement to create an ad hoc query plan that would be similar to the one that worked correctly.
I am working on a problem where I need to add an OR clause to a set of existing conditions. The current conditions are built in a hash in a method and at the end, they are used in the where clause. Here is a simplified example:
...
conds.merge!({:users => {:archived => false}})
Model.where(conds)
I am trying to add an OR clause to the current set of conditions so it would be something like '(conditions) OR new_condition'. I'd like to add the OR statement without converting each addition to the conds hash into a string. That would be my last option. I was hoping someone has done something like this before (without using Arel). I seem to recall in Rails 2 there was a way to parse a conditions hash using a method from the model (something like Model.some_method(conds) would produce the where clause string. Maybe that would be a good option to just add the OR clause on to that string. Any ideas are appreciated. Thank you for your help!
I found a way to do what I needed. Instead of changing all of the conditions that I am building, I am parsing the conditions to SQL using sanitize_sql_for_conditions. This is a private method in ActiveRecord, so I had to put a method on the model to allow me to access it. Here is my model method:
def self.convert_conditions_hash_to_sql(conditions)
self.sanitize_sql_for_conditions(conditions)
end
So, once I convert my conditions to text, I can add my OR clause (along with the appropriate parentheses) to the end of the original conditions. So, it would go something like this:
Model.where('(?) OR (model.type = ? AND model.id IN(?))', Model.convert_conditions_hash_to_sql(conds), model_type, model_id_array)
I have a string returned from a function "'aa','bb','cc',..."(the function uses GROUP_CONCAT). I want to use this as a condition in the IN clase of mysql.
SELECT name,class,comment
FROM vwstudent v
WHERE name IN (select func())
I want the query to act like
SELECT name,class,comment
FROM vwstudent v
WHERE name IN ('aa','bb','cc','dd',..)
I assume ('aa','bb','cc','dd',..) is acting as a whole string here and isn't generating any result. What can I do to run this query error less.
I'm not sure if it'll help. But you might be able to hack something together by using PREPARE and EXECUTE as described here: How To have Dynamic SQL in MySQL Stored Procedure
... but that's completely new to me. I've never used anything like that in MySQL.
I am using lua script
https://github.com/clofresh/mysql-proxy-cache to cache the select query.
But there is a problem with the way it is detecting select statement.
It is using following code
return query:sub(1,6):lower() == 'select'
This will not work if select query is nested in (). Example:
(SELECT * from tbl_name);
Is there a way to remove extra () in mysql proxy ?
or Is there a better way to detect select query?
I would try to write a normalizing script using the String Library that detect common patterns and replaces them with equivalent normalized sql.
One example is your parenteses but also queries where the where parts have been moved around could benefit from this.
The queries are actually inside of the the parentheses, not inside of a string? That shouldn't parse correctly, even with a plug in. If it is in a string then simply use :sub(2, 7), however, if it is not, then put it inside of a string. Create a function that basically reproduces the function, except puts it in a string, e.g.:
function mysqlQuery(mysqlString)
loadstring(mysqlString)();
return mysqlString;
end
mysqlQuery("SELECT * from tbl");