Pyspark : Dynamically prepare pyspark-sql query using parameters - apache-spark

What are the different ways to dynamicaly bind parameters and prepare pyspark-sql statament.
Example:
Dynamic Query
query = '''SELECT column1, column2
FROM ${db_name}.${table_name}
WHERE column1 = ${filter_value}'''
Above dynamic query have ${db_name}, ${table_name} and ${filter_value} variables, These variables will get values from run time parameters.
Parameter Details:
db_name = 'your_db_name'
table_name = 'your_table_name'
filter_value = 'some_value'
Expected Query after Binding Parameters in Dynamic Query
SELECT column1, column2
FROM your_db_name.your_table_name
WHERE column1 = some_value

Here are few options to prepare pyspark-sql through binding parameter.
Option#1 - Using String Interpolation / f-Strings (Python 3.6+)
db_name = 'your_db_name'
table_name = 'your_table_name'
filter_value = 'some_value'
query = f'''SELECT column1, column2
FROM {db_name}.{table_name}
WHERE column1 = {filter_value}'''
Option#2 - Using String Formatting (str.format)
query = '''SELECT column1, column2
FROM {}.{}
WHERE column1 = {}'''
db_name = 'your_db_name'
table_name = 'your_table_name'
filter_value = 'some_value'
query.format(db_name, table_name, filter_value)
Option#3 - Using Template String
query = '''SELECT column1, column2
FROM ${db_name}.${table_name}
WHERE column1 = ${filter_value}'''
db_name = 'your_db_name'
table_name = 'your_table_name'
filter_value = 'some_value'
from string import Template
t = Template(query)
t.substitute(db_name=db_name, table_name=table_name, filter_value=filter_value)
String Interpolation/f-Strings (Option#1) is recommended if you have
python 3.6+ else use String Formatting str.format (Option#2)
Template String are more useful to handle user supplied string
(Option#3)

Related

node.js - retrieve table name using regex from insert statement if table name exists in SQL string

I have an input string in node.js with uncertain format. this input string is an Insert SQL Query. can anybody suggest a fast and high performance piece of code to store my_table_name in variable?
INseRT IntO my_table_Name (CustomerName) VALUES ('Cardinal');
INseRT into my_Table_name (CustomerName) VALUES ('Cardinal');
INsert into my_table_name (CustomerName) VALUES ('Cardinal');
thanks.
You can use a simple regex to find the table name, for example:
const query1 = "INseRT IntO my_table_Name (CustomerName) VALUES ('Cardinal');"
const query2 = " INseRT into my_Table_name (CustomerName) VALUES ('Cardinal');"
const query3 = " INsert into my_table_name (CustomerName) VALUES ('Cardinal');"
const queries = [query1, query2, query3];
pattern = /insert\s+into\s+(.*?)\s/i;
for (const query of queries) {
const matches = query.match(pattern);
if (matches) {
const tableName = matches[1]
console.log(tableName)
}
}
>>> my_table_Name
>>> my_table_Name
>>> my_table_Name

How to get table names from Presto query using presto-parser?

Not able to extract table names used within with clause, I'm using presto-parser version 0.226.
SqlParser sqlParser = new SqlParser();
String sql = "WITH dataset AS ( SELECT ROW('Bob', 38) AS users from tabb ) SELECT * FROM dataset";
Query query = (Query)sqlParser.createStatement(sql, ParsingOptions.builder().build());
QuerySpecification body = (QuerySpecification)query.getQueryBody();
System.out.println("From = " + body.getFrom().get());
/* Output
From = Table{dataset}
*/
Expected output
From = Table{dataset, tabb}

How to create update query with QSqlQuery

I'm trying to create an update query in Python3/PyQt5.10/Sqlite . A select/insert query made the same way runs fine. Fields & corresponding record exist.
def updateRecords():
theDict = {
"Loc": "PyQt121",
"BoekNr" : "dfdf",
"BoekTitel" : "eeee",
"BoekBedrag" : 999
}
theFilter = " WHERE Loc = 'PyQt'"
query = QSqlQuery()
columns = ', '.join(pDict.keys())
placeholders = ':'+', :'.join(pDict.keys())
sql = 'UPDATE %s SET (%s) VALUES (%s) %s' % (pTable, columns, placeholders, pFilter)
query.prepare(sql)
for key, value in pDict.items():
query.bindValue(":"+key, value)
print (sql)
query.exec_()
print(query.lastError().databaseText())
return query.numRowsAffected()
The sql generated is UPDATE tempbooks SET (Loc, BoekNr, BoekTitel, BoekBedrag) VALUES (:Loc, :BoekNr, :BoekTitel, :BoekBedrag) WHERE Loc = 'PyQt'.
query.lastError().databaseText()) give me "No Query" and updated rows is -1.
The correct syntax for an update query:
UPDATE tablename
set col1 = val1,
col2 = val2,
col3 = val3
WHERE condition
Probably query.prepare(sql) is returning False because of invalid syntax.

How to get a word from a sentence using regex nodejs

I have a use case where I need to get the table name from my sql query
like suppose I have
select * from schema.tableName
OR
select * from schema.tableName where id = 123
OR
select column1, column2, column3 from schema.tableName where id = 123
In need to get 'schema.tableName' from the sql query in above cases , how it can be done using regex in Node.
I have tried (?<=from)(\s+\w+\b)
but I am getting warning that look behind is not supported in javascript.
A RegEx that will match the table name from queries similar to the ones you provided as examples can be written easily.
Try this RegEx: /select .* from ([^ ]*)/i
See the complete code below:
var sql1 = "select * from tableName";
var sql2 = "select * from tableName where id = 123";
var sql3 = "select column1, column2, column3 from tableName where id = 123";
var t1 = sql1.match(/select .* from ([^ ]*)/i);
var t2 = sql2.match(/select .* from ([^ ]*)/i);
var t3 = sql3.match(/select .* from ([^ ]*)/i);
console.log(t1[1]);
console.log(t2[1]);
console.log(t3[1]);
However, the RegEx will get complex if you would need to match table name from all the possible valid select queries.
EDIT
You can use a stripped down version of the above RegEx to get the same results.
/ from ([^ ]*)/i
Maybe something like this:
var query = "select column1, column2, column3 from schema.tableName where id = 123"
var result = query.match(/from\s+([\.\w]+)+\s+/i);
var tableName = null;
if (result && result.length > 1) {
tableName = result[1];
}

TSQL String modify

I have a problem with string.
I have a variable #Rights which looks like 'ASD,ZXC,QWE,IOP,JKL'
What I need to do is use this string in
SELECT * FROM dbo.Example
WHERE Rights IN (#Rights)
Problem is that I need to convert:
'ASD,ZXC,QWE,IOP,JKL'
to:
'ASD','ZXC','QWE','IOP','JKL'
How can I do this?
you can create a split function
CREATE FUNCTION [dbo].[Split]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
GO
and after you can convert the string in a temp table
DECLARE #Rights NVARCHAR(128)
SET #Rights = 'ASD,ZXC,QWE,IOP,JKL'
SELECT *
INTO #Temp
FROM dbo.Split(#Rights , ',')
and after you can use it in your query like this
SELECT * FROM dbo.Example
WHERE Rights IN (SELECT Data FROM #Temp)
You can try like this:
DECLARE #xml xml, #str varchar(100), #delimiter varchar(10)
SET #str = 'ASD,ZXC,QWE,IOP,JKL'
SET #delimiter = ','
SET #xml = cast(('<X>'+replace(#str, #delimiter, '</X><X>')+'</X>') as xml)
SELECT C.value('.', 'varchar(10)') as value FROM #xml.nodes('X') as X(C)
SQL DEMO
You can use Dynamic SQL:
LiveDemo
-- sample data
CREATE TABLE #Example(ID INT IDENTITY(1,1), Rights VARCHAR(100));
INSERT INTO #Example VALUES ('ASD'), ('ABC'), ('IOP');
DECLARE #Rights NVARCHAR(MAX) = 'ASD,ZXC,QWE,IOP,JKL';
DECLARE #sql NVARCHAR(MAX) =
N'SELECT *
FROM #Example
WHERE Rights IN (''<placeholder>'')';
SET #sql = REPLACE(#sql, '<placeholder>', REPLACE(#Rights, ',', ''','''));
-- SELECT #sql; -- for debug
EXEC dbo.sp_executesql
#sql;
But you should reconsider using Table Valued Parameter instead.

Resources