How do I make a dynamic query without SQL injection in n=Node.js SQL Server?
I used this query to prevent SQL injection.
const conn = await pool;
conn.query`select * from TEST where id = ${test}`;
But sometimes I have to add a WHERE Clause.
I tried this, but an error occurred.
let addwhere = `AND name = ${name}}`;
conn.query`select * from TEST where id = ${test} ${addwhere}`;
How do I dynamically add where conditions?
Related
I have my sql server present at azure portal (basically I am using mssql) and I am trying to create a new database using NodeJs API call
basically my API looks like this "http://localhost:9000/api/dbcreation/test/customer" where my controller name is dbcreation, test is my database name where the store procedure present to create a new database and customer is my new database name.
Below is the model code which is called by the dbcreation controller to execute the query and #dbname value is the new database name (customer) which I am trying to fetch from the API
exports.get = async function (customerdb, dbname){
var param_list = [];
param_list.push({
"param_name": "dbname",
"param_type": "string",
"param_value": dbname
});
var query = `exec p_dbCreation #dbname`;
return db.sqldb.execute_read_query(query, customerdb, param_list);
}
And below is my stored procedure code
ALTER PROCEDURE [dbo].[p_dbCreation] #database_name nvarchar(30)
AS
CREATE DATABASE [#database_name] (EDITION = 'Standard', SERVICE_OBJECTIVE = ELASTIC_POOL (name = [xxxxx]), MAXSIZE = 250 GB) WITH CATALOG_COLLATION = SQL_Latin1_General_CP1_CI_AS;
GO
when I call the api the call is getting executed successfully but the database is getting created with the name #database_name it is not fetching the parameter value which I passed. Can you please help me with this ?
This issue is casued by your T-SQL script. We need to dynamically splice the SQL statement and then execute it. The script should be as follows:
alter PROCEDURE [dbo].[p_dbCreation] #database_name nvarchar(30)
AS
declare #sql nvarchar(2000)
set #sql='CREATE DATABASE '+#database_name+'(EDITION = ''Standard'', SERVICE_OBJECTIVE = ELASTIC_POOL (name = [xxxxx]), MAXSIZE = 250 GB) WITH CATALOG_COLLATION = SQL_Latin1_General_CP1_CI_AS;'
BEGIN
EXEC(#sql)
END
Is there a way to get Sequelize to build a query with the replacements (so I'll be able to use their SQL injection cleanup) and just get the raw SQL query, without executing it?
You can just call the QueryGenerator with the type of query you want to generate.
For example a selectQuery:
const sql = MyModel.QueryGenerator.selectQuery(
MyModel.getTableName(), {
where: {
someAttribute: "value"
},
attributes: ["other", "attributes"]
},
MyModel);
There's also insertQuery, updateQuery, deleteQuery too.
It looks like this feature isn't implemented yet, but there are some users trying to push the issue forward.
See github issue.
it's undocumented, but I use next way (Sequelize ver. 5.2.13):
let tableName = myModel.getTableName(options);
let qi = myModel.QueryInterface;
options.type = 'SELECT';
options.model = myModel;
var sql = qi.QueryGenerator.selectQuery(tableName, options, myModel);
I have a project with that is using Slick 3.1.0 with jTDS as the JDBC driver. When I enable connection pooling, which is using HikariCP, I get the following exception:
java.sql.SQLException: JDBC4 Connection.isValid()
method not supported, connection test query must be configured
So for SQL Server the SQL query would be SELECT 1. My question is: When using Slick, how do I set properties for HikariCP? Is there some property to set in the config file? I tried the following to no effect:
jtds {
driver = "net.sourceforge.jtds.jdbc.Driver"
url = "jdbc:jtds:sqlserver://foobar.org:1433/somedatabase"
user = "theUser"
password = "theSecretPassword"
properties {
connectionTestQuery = "SELECT 1"
}
}
Found the solution to my own question. The HikariCP properties just go straight into the config file. For example, the solution to setting the connection test query was:
jtds {
driver = "net.sourceforge.jtds.jdbc.Driver"
url = "jdbc:jtds:sqlserver://foobar.org:1433/somedatabase"
user = "theUser"
password = "theSecretPassword"
connectionTestQuery = "SELECT 1"
}
I'm trying to retrieve a list of entities from CRM, but I'd like to get each one with the related entities. So far, I've the following code:
FilterExpression filterExpression = new FilterExpression();
ConditionExpression condition = new ConditionExpression(Constants.ModifiedOnAttribute, ConditionOperator.GreaterEqual, lastSync);
filterExpression.AddCondition(condition);
QueryExpression query = new QueryExpression()
{
EntityName = entityName,
ColumnSet = new ColumnSet(attributesMetadata.Select(att => att.Name).ToArray<string>()),
Criteria = filterExpression,
Distinct = false,
NoLock = true
};
RetrieveMultipleRequest multipleRequest = new RetrieveMultipleRequest();
multipleRequest.Query = queryExpression;
RetrieveMultipleResponse response = (RetrieveMultipleResponse)proxy.Execute(multipleRequest);
In the variable response, I can see the EntityCollection attribute, but inside, Related entities always come empty.
I'd like to know if it is possible to retrieve the set of a given entities, with the related entities, using RetrieveMultipleRequest, rather than go one by one using RetrieveRequest.
One approach to retreive related entities data - adding LinkEntities to your query. Example below will make you an idea how to make this:
LinkEntity linkEntity = new LinkEntity("email", "new_emails", "activityid", "new_relatedemail", JoinOperator.Inner);
linkEntity.Columns.AddColumn("versionnumber");
linkEntity.Columns.AddColumn("new_emailsid");
linkEntity.EntityAlias = "related";
query = new QueryExpression("email");
query.ColumnSet.AddColumn("activityid");
query.ColumnSet.AddColumn("versionnumber");
query.Criteria.AddCondition("modifiedon", ConditionOperator.NotNull);
query.LinkEntities.Add(linkEntity);
And then you can access attributes from related entities using EntityAlias you specified above:
foreach (Entity entity in entities.Entities)
{
if ((long)(entity["related.versionnumber"] as AliasedValue).Value > 0)
{
stop = false;
}
}
The RetrieveMultipleRequest is for returning multiple instances of a particular type of entity. I have spent a year using the CRM SDK from C# and I have found no way of populating those related entity collections in a single query. This basically leaves you with two options:
Use the AliasedValue as SergeyS recommends. Remember when querying 1:Many relationships, be aware that you could be returning multiple results for the same parent entity. This is what I use most of the time.
Perform a second query for each relationship you want access to. You'll probably get better performance if you can use an IN statement in your second query, based on the results of the first, rather than performing a separate query for each result of the first.
Below is some pseudo code to show the difference.
var contacts = GetContacts();
// One Request to get the cars for the contacts
var cars = GetCarsWhereContactIdIn(contacts.Select( c => c.new_ContactId));
foreach(var c in contacts){
c.new_Cars.AddRange(cars.where(car => car.new_contactId = c.ContactId));
}
// Verses
var contacts = GetContacts();
foreach(var c in contacts){
// One Request for each contact
c.new_Cars.AddRange(GetCarsForContact(c.ContactId));
}
Does ToFuture works with nhibernate linq? If so, how do you use it?
Be carefull ToFuture only works if the database driver supports MulitpleQueries. This is only the case in some drivers (eg. MySql, SqlServer) but not in all (eg. Oracle)
Yes it does. Here's a simple example:
var blogs = _session.Query<Blog>()
.Take(30)
.ToFuture();
var blogCount= _session.Query<Blog>()
.ToFutureValue(x => x.Count());
Console.WriteLine(blogCount.Value); // DB is queried here.
Here's an example of where I've used it for a customer search form that displayed paged search results and and a total count of search results. Notice you can reuse an IQueryable to create two futures. The Filter methods built an IQueryable based on what fields the user searched by.
int resultsPerPage = 50;
var query = _session.Query<CustomerSearch>()
.FilterById(model)
.FilterByFirstName(model)
.FilterByLastName(model)
.FilterBySocialSecurityNumber(model)
.FilterByPrimaryPhoneNumber(model);
var futureResults = query
.OrderBy(x => x.Id)
.Skip(model.Page * resultsPerPage)
.Take(resultsPerPage)
.ToFuture();
var futureCount = query.ToFutureValue(x => x.Count());