Reputation: 35359
I need to add if conditions to my SQL query. I came up with this solution, but it does not work, and I'm not sure why.
local.platformId = arguments.platformId ? "AND platforms.id = #arguments.platformId#" : "";
local.pages = new Query(dataSource=variables.wheels.class.connection.datasource);
local.pages.setSQL
("
SELECT COUNT(games.id) AS totalRecords
FROM games
INNER JOIN platforms ON games.platformId = platforms.id
WHERE 0=0
:platform
");
local.pages.addParam(name="platform", cfsqltype="CF_SQL_VARCHAR", value=local.platformId);
local.pages = local.pages.execute().getResult();
I get an error of: You have an error in your SQL syntax; check ... near ''AND platforms.id = 1' ''' at line 6
Any idea how to get around this limitation and still ensure safety from SQL injection?
Upvotes: 3
Views: 2449
Reputation: 7786
Why not set the SQL and add the param if neccessary in a conditional statement in your code?
local.pages = new Query(dataSource=variables.wheels.class.connection.datasource);
local.baseSQL = "
SELECT COUNT(games.id) AS totalRecords
FROM games
INNER JOIN platforms ON games.platformId = platforms.id
WHERE platforms.id = :platform
";
if(StructKeyExists(arguments, "platformId")
{
local.baseSQL &= "AND platforms.id = :platformId";
local.pages.setSQL(baseSQL);
local.pages.addParam(
name="platformId",
cfsqltype="CF_SQL_VARCHAR",
value=arguments.platformId);
}
else
local.pages.setSQL(baseSQL)
local.pages = local.pages.execute().getResult();
Upvotes: 2
Reputation: 19834
I like using savecontent for this:
savecontent variable="local.sql"{
WriteOutput("
SELECT COUNT(games.id) AS totalRecords
FROM games
INNER JOIN platforms ON games.platformId = platforms.id
WHERE 0=0
");
(arguments.platformId)
? WriteOutput("AND platforms.id = :platform")
: WriteOutput("");
}
local.pages = new Query(dataSource=variables.wheels.class.connection.datasource);
local.pages.setSQL(local.sql);
if (arguments.platformId){
local.pages.addParam(name="platform", cfsqltype="CF_SQL_VARCHAR", value=arguments.platformId);
}
local.pages = local.pages.execute().getResult();
Upvotes: 6
Reputation: 31920
addParam is the equivalent of using cfqueryparam in CFML. So it's expecting the value attribute to be like '1' or 'foobar', not a bit of SQL. Instead just set the value of platformID to either be the arguments.platformid or an empty string. Then refer directly to :platform in your WHERE clause.
local.platformId = arguments.platformId ? arguments.platformId : "";
local.pages = new Query(dataSource=variables.wheels.class.connection.datasource);
local.pages.setSQL
("
SELECT COUNT(games.id) AS totalRecords
FROM games
INNER JOIN platforms ON games.platformId = platforms.id
WHERE platforms.id = :platform
");
local.pages.addParam(name="platform", cfsqltype="CF_SQL_VARCHAR", value=local.platformId);
local.pages = local.pages.execute().getResult();
This article here has some good info: http://www.bennadel.com/blog/1678-Learning-ColdFusion-9-Using-CFQuery-And-Other-Service-Tags-In-CFScript.htm
Upvotes: 3