jdbcTemplate query only executes with SELECT * - postgresql

Long time lurker and learner, first time question here. I'm working a project for a local library to pull some data from their database to help the employees pull books put on hold for patrons. The catch here is the access to the database is read only. I cannot create any temporary tables or views.
We've created a long query to generate the data needed, I used a couple CTEs to whittle things down and then there's some logic based on which location the book may reside in to show where it should pick from. All in all, we're happy with the query results.
When I try to implement it using jdbcTemplate, I can't seem to find a way to get anything other than SELECT * to work.
WITH holdCTE1 (holdID, itemID, ...) AS (
SELECT *
FROM
table 1,
table 2,
table 3
WHERE
yada yada
This will give me results if I then do a SELECT * FROM holdCTE1.
If instead I specify columns, like this
WITH holdCTE1 (holdID, itemID, ...) AS (
SELECT t1.holdID, t2.itemID, t3.title
FROM
table 1,
table 2,
table 3
WHERE
yada yada
I get a syntax error at the first from table, regardless. I've tried adjusting all my table JOINs and using aliases and just about everything I can come across, but it doesn't seem to help.
A couple of things we're using to help the filtering and such, since we can't create a view to make it easy, is to call out the subqueries, so for example, in CTE1 we add a final column
'bib hold' AS hold_type
Even with the SELECT *, 'bib hold AS hold_type, I get the same syntax error. The actual wording of the error is:
StatementCallback; bad SQL grammar ... then my query ... nested exception is org.postgresql.util.PSQLException: ERROR: syntax error at or near ... the first thing under the FROM line
The library is using a Postgresql database, and I'm using Spring with jdbcTemplate for the SQL side.
Thanks in advance for looking.

Sorry for the poorly worded question, but I think I stumbled across an answer this evening. I was checking all of my queries I'd noted in pgAdmin, and I did a copy/paste into my java class.
With the escape characters, the code seems to run just fine. So this looks like it is passing info correctly to the query
WITH hold_bib (hold_id, item_id, birl_bib, patron, status, hold_type) AS (SELECT\n"
+ " h.id,\n"
+ " i.record_id,\n"
+ " birl.bib_record_id,\n"
+ " h.patron_record_id,\n"
+ " i.item_status_code,\n"
+ " 'bib'AS hold_type\n"
The function looks like this at the beginning now:
public List<Hold> libraryNotPicked() {
String sql = "\n"
+ "WITH hold_bib (hold_id, item_id, birl_bib, patron, status, hold_type) AS (SELECT\n"
+ " h.id,\n"
+ " i.record_id,\n"
+ " birl.bib_record_id,\n"
+ " h.patron_record_id,\n"
+ " i.item_status_code,\n"
+ " 'bib'AS hold_type\n"
...
+ " ;
List<Hold> holds = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Hold.class));
return holds;
Seems to me the key is the \n type characters in the query.

Related

I need to change the output of a query so that instead of it coming back as the abbreviation 'em' it says 'employee'. Tsql

I have the correct result coming back. I just need to convert 6 abbreviations in that result to their correct names. There are 20k names assigned to 1 of 6 abbreviated names.
I tried aliasing but that seems to only work for table names.
I tried doing a case statement but that didn't work.
You need to provide more details (like some sample input and output), but if you have data like EM100, and you want to make it EMPLOYEE 100, then you could use an expression such as:
CASE WHEN ColumnName like 'EM%' THEN 'EMPLOYEE ' + SUBSTRING (ColumnName,3,100)
WHEN ColumnName like 'RN%' THEN 'REGNURSE' + SUBSTRING (ColumnName,3,100)
else ColumnName END
But providing more details will help provide a more specific answer.

Is this kind of code prone to SQL injection?

I am doing a project for my school and I am task to debug all of the issues found using the application call HPE Fortify. The report generated by the application only indicates the code below prone to SQL injection:
String sql = " select Distinct p1.desc1,p2.desc2 from parameter p1"
+" inner join parameter p2"
+" on p1.ParaCode1='CR_DERIVE' and p1.ParaCode2=p2.Desc2"
+" inner join parameter p3"
+ " on p2.ParaCode3=p3.ParaCode1 and p3.ParaCode3=p2.Desc2"
+" where p2.paracode1='ATTRIBUTE'"
+ " and p2.ParaCode2='" + ddl_attribute.SelectedValue + "'";
But not the codes below:
strSQL = "SELECT Paracode2 FROM Parameter WHERE Paracode1 = 'PROGMGR' AND Desc1 = '" + login + "' AND Status = 'A' ";
I would like to know the reason why as I am unclear regarding SQL injection and I am new to this. Thanks for the response
You're concatenating some application variables into your SQL query string, so the safety depends on how those variables' values were set. Did they come from some untrusted input? Or were they set from some safe application data?
If HPE Fortify has analyzed your code and knows how your login variable was assigned its value, it may be able to tell that it's safe to use in an SQL expression. Whereas it may not be able to make that conclusion about the SelectedValue variable, so it assumes it's unsafe and therefore could cause an SQL vulnerability.
The Perl language does something similar, without the use of a tool like HPE Fortify. Every Perl variable is either "tainted" or "untainted" depending on where it got its value. So you can tell whether a variable is safe to use in SQL, or in eval() or other possible code-injection situations. It's a pity more languages don't support something similar.
But I agree with other commenters that you should learn to use query parameters. It's easy and it's safe. And you can stop getting eyestrain figuring out if you've balanced your quotes-within-quotes correctly.
Your code sample looks like it might be Java. Here's an example in Java:
strSQL = "SELECT Paracode2 FROM Parameter"
+ " WHERE Paracode1 = 'PROGMGR' AND Desc1 = ? AND Status = 'A' ";
Notice the ? placeholder for the parameter has no single-quotes around it within the SQL string. You must not put SQL quotes around the placeholder.
PreparedStatement stmt = con.PreparedStatement(sql);
stmt.setString(1, login);
ResultSet rs = stmt.executeQuery();
For more information to help you understand SQL injection, you might like my presentation SQL Injection Myths and Fallacies, or the video of me delivering that talk: https://www.youtube.com/watch?v=VldxqTejybk

SQLRPGLE DB2 Select into variable

I'm having problems with my query returning errors. What I have at this moment is this:
comi C X'7D'
SqlQuery S 500A
VarSel S 10A
VarSel = *blanks;
SqlQuery = 'select USU into VarSel from FXXUSELN ' +
'where USU = upper(' + comi + %trim(pusuario) +
comi + ') and PWDUSU = upper(' + comi +
%trim(ppassword) + comi + ')';
Exec SQL execute immediate :SqlQuery;
psqlcod = sqlcod;
But when I try to debug that code, it returns -084: UNACCEPTABLE SQL STATEMENT as sqlcod. Printing the SqlQuery variable in the debugger call I get this string, which seems to be correct:
select USU into VarSel from FXXUSELN where USU = upper('usua
rio') and PWDUSU = upper('password')
Anybody knows how to solve this problem so I can make a login stored procedure? Thanks in advance.
The problem is that SELECT INTO can not be dynamically prepared.
If you look at the Invocation section of SELECT INTO in the manual you'll see:
This statement can only be embedded in an application program. It is an executable statement that cannot be dynamically prepared. It must not be specified in REXX.
Also note the following Actions Allowed on SQL Statements section of appendix B in the manual which summarizes where/how each statement may be used.
Finally, if what you tried had worked, you'd have opened yourself up to SQL Injection attacks. Generally speaking, for any DB you should avoid dynamic SQL. If you must use dynamic SQL, then you should use parameter makers instead of directly concatenating user input into the string.
In your case, there's no need for dynamic SQL if the first place. Static SQL is easier, safer, and allows the use of SELECT INTO
exec SQL
select USU into :VarSel from FXXUSELN
where USU = upper(:pusuario)
and PWDUSU = upper(:ppassword);

Access 2007 VBA: use Form.Filter in query parameters

I'd like to create and open a select query based on the user's current form filters. I can do this in VBA by parsing the form's Me.Filter string, extracting the bits I need and building a WHERE statement. However, putting in the all the required logic, punctuation and syntax is going to be a pain.
So my question, before I do all that is: is there any existing function to do this?
Thanks.
Maybe my comment was a little cryptic.
Let's say the recordsource of your form is myQuery.
The form is filtered, Me.Filter = myQuery.field1 LIKE 'asdf*' AND myQuery.field2 = 42
So your select query is e.g.
SELECT field1, field3
FROM myQuery
WHERE myQuery.field1 LIKE 'asdf*' AND myQuery.field2 = 42
or
myQuerydef.SQL = "SELECT field1, field3 FROM " & Me.Recordsource & _
" WHERE " & Me.Filter
So I don't quite see where the problem is.
The answer to your question is no, there is no function - but you shouldn't need anything besides Me.Filter.
Edit as suggested by HansUp:
If the RecordSource of your form currently isn't a single query, but a SELECT statement, create a named query from that SELECT statement, and use that query as RecordSource.

Neo4j Cypher query to find nodes with exact match (AND instead of OR)

I'm trying to create a query that bring me some node that have the exact match with a set of nodes. In this case I wanna bring experiences that have tags, for example, what experiences have tags: "food" AND "nightlife" AND "culture".
My query is "working", but bringing the result using OR instead of AND. How can I fix it?
I'm not sure if I'm using de correct approach of the
#Query("START experience = node:__types__(className=\"...\"), tags = node({0}) " +
"WHERE experience-[:TAGGED]->tags " +
"RETURN experience")
public Set<Experience> findExperiencesByTags(Set<Long> tagIds);
I'm using Spring Data 2.0.1 and neo4j 1.6.3.
try to divide it into 3 separate MATCH phrases:
"MATCH experience-[:TAGGED]->tags1, experience-[:TAGGED]->tags2, experience-[:TAGGED]->tags3, " +
"WHERE tags1.tag='food' AND tags2.tag='culture' AND tags3.tag='nightlife' "
I agree with #ulkas
If you really want to pass in an arbitrary number of tags you can try this, but it will probably perform not as good as the explicit matches.
START tags = node({0})
MATCH experience-[:TAGGED]->tags
WITH experience, count(*) as cnt
WHERE cnt = length({0})
RETURN experience