I'm adventuring with sparql and a java application, I've found a few connection basics to get up and running as it were but fear I'm making a mistake which will later turn into something worse.
Every connection suggestion regardless of the library used says to connect to "http://dbpedia.org/sparql/" yet this doesn't work for me.
I checked the url that is returned when I run a query using the online editor and noticed the live prefix, so I added that as my connection string, and it works. That is to say, my connection string looks like "http://live.dbpedia.org/sparql"
And it does return the result, however, the result has the XML Schema attached which is making me wonder whether or not it's because of this live. I've added in.
Below is the simple connection code I'm using, is this correct? Any and all help greatly appreciated thank you.
If the 'live' is correct, is it possible to extra the just the value wihtout the Schema?
StringBuilder sb = new StringBuilder();
sb.append("PREFIX dbr: <http://dbpedia.org/resource/> \n");
sb.append("PREFIX dbp: <http://dbpedia.org/property/> \n");
sb.append("PREFIX dbo: <http://dbpedia.org/ontology/> \n");
sb.append("SELECT ?dob \n");
sb.append("WHERE {dbr:Tony_Blair dbp:birthDate ?dob} \n");
Query query = QueryFactory.create(sb.toString());
QueryExecution qexec = QueryExecutionFactory.sparqlService("http://live.dbpedia.org/sparql", query);
try {
ResultSet results = qexec.execSelect();
for ( ; results.hasNext() ; )
{
QuerySolution soln = results.nextSolution() ;
System.out.println(soln.get("?dob"));
}
the result being:
1953-05-06^^http://www.w3.org/2001/XMLSchema#date
Well the result as you show it is missing some brackets and quotes, but I assume that is caused by how you copy-pasted it. More usually it would look like this:
"1953-05-06"^^<http://www.w3.org/2001/XMLSchema#date>
But in essence your query and code is correct. The "attached XML Schema" here is the datatype of the returned literal string.
An RDF literal consists of a lexical value (in your case "1953-05-06") and a datatype (in your case http://www.w3.org/2001/XMLSchema#date). It can also, optionally have a language tag e.g. "colour"#en-UK.
If you wish to remove the datatype from the result and only retrieve the lexical value, you can use the STR() function as part of the SELECT clause in your query:
SELECT (STR(?dob) as ?date_of_birth)
As for the connection string that you are struggling with: there are two separate DBPedia endpoints. The "regular" one is http://dbpedia.org/sparql (no trailing slash) - this queries a static dataset that is synced/updated with Wikipedia changes every so 6 months or so. The "live" endpoint, http://live.dbpedia.org/sparql, is an effort to have a more up-to-date dataset ready for querying. See https://wiki.dbpedia.org/online-access/DBpediaLive for more details.
Related
I have just started learning Couchbase. I am trying to write a basic query using java sdk but I am not able to understand how to write it. Below is the query:
SELECT *
FROM users_with_orders usr
JOIN orders_with_users orders
ON KEYS ARRAY s.order_id FOR s IN usr.shipped_order_history END
This is for joining without array:
LetPath path = select("*,META(usr).id as _ID,META(usr).cas as _CAS).from(bucketName +" usr").join(bucketname +" orders").onKeys("usr.order_id)
How should I proceed with the above query for on keys array?
Thanks!!!!
As described in the docs on Querying from the SDK, you can use either a simple string with the Java SDK or use the DSL. For example:
// query with a simple string
System.out.println("Simple string query:");
N1qlQuery airlineQuery = N1qlQuery.simple("SELECT `travel-sample`.* FROM `travel-sample` WHERE name=\"United Airlines\" AND type=\"airline\"");
N1qlQueryResult queryResult = bucket.query(airlineQuery);
for (N1qlQueryRow result: queryResult) {
System.out.println(result.value());
}
//query with a parameter using the DSL
System.out.println("Parameterized query using the DSL:");
Statement statement = select(path(i("travel-sample"), "*")).from(i("travel-sample")).where(x("name").eq(x("$airline_param")).and(x("type").eq(s("airline"))));
JsonObject placeholderValues = JsonObject.create().put("airline_param", "United Airlines");
N1qlQuery airlineQueryParameterized = N1qlQuery.parameterized(statement, placeholderValues);
N1qlQueryResult queryResultParameterized = bucket.query(airlineQueryParameterized);
for (N1qlQueryRow row : queryResultParameterized) {
System.out.println(row);
}
(I posted a full gist of this example for the imports, etc.)
See the docs for more info, but you may want to use the DSL to allow IDE code completion and Java compile time checking. When developing an interactive web application, you'll probably also want to use parameterized statements (for security) and may even want prepared statements (for performance).
I am using jdbc PreparedStatement for data insertion.
Statement stmt = conn.prepareStatement(
"INESRT INTO" + tablename+ "("+columnString+") VALUES (?,?,?)");
tablename and columnString are something that is dynamically generated.
I've tried to parameterise tablename and columnString but they will just resolve to something like 'tablename' which will violate the syntax.
I've found somewhere online that suggest me to lookup the database to check for valid tablename/columnString, and cache it somewhere(a Hashset perhaps) for another query, but I'm looking for better performance/ quick hack that will solve the issue, perhaps a string validator/ regex that will do the trick.
Have anyone came across this issue and how do you solve it?
I am not a java-guy, so, only a theory.
You can either format dynamically added identifiers or white-list them.
Second option is way better. Because
most developers aren't familiar enough with identifiers to format them correctly. Say, to quote an identifier, which is offered in the first comment, won't make it protected at all.
there could be another attack vector, not entirely an injection, but similar: imagine there is a column in your table, an ordinary user isn't allowed to - say, called "admin". With dynamically built columnString using data coming from the client side, it's piece of cake to forge a privilege escalation.
Thus, to list all the possible (and allowed) variants in your code beforehand, and then to verify entered value against it, would be the best.
As of columnString - is consists of separate column names. Thus, to protect it, one have to verify each separate column name against a white list, and then assemble a final columnString from them.
Create a method that generates the sql string for you:
private static final String template = "insert into %s (%s) values (%s)";
private String buildStmt(String tblName, String ... colNames) {
StringJoiner colNamesJoiner = new StringJoiner(",");
StringJoiner paramsJoiner = new StringJoiner(",");
Arrays.stream(colNames).forEach(colName -> {
colNamesJoiner.add(colName);
paramsJoiner.add("?");
});
return String.format(template, tblName, colNamesJoiner.toString(), paramsJoiner.toString());
}
Then use it...
Statement stmt = conn.prepareStatement(buildStmt(tablename, [your column names]));
As an elaboration on #Anders' answer, don't use the input parameter as the name directly, but keep a properties file (or database table) that maps a set of allowed inputs to actual table names.
That way any invalid name will not lead to valid SQL (and can be caught before any SQL is generated) AND the actual names are never known outside the application, thus making it far harder to guess what would be valid SQL statements.
I think, the best approach is to get table and columns names from database or other non user input, and use parameters in prepared statement for the rest.
There are multiple solutions we can apply.
1) White List Input Validation
String tableName;
switch(PARAM):
case "Value1": tableName = "fooTable";
break;
case "Value2": tableName = "barTable";
break;
...
default : throw new InputValidationException("unexpected value provided for table name");
By doing this input validation on tableName, will allows only specified tables in the query, so it will prevents sql injection attack.
2) Bind your dynamic columnName(s) or tableName(s) with special characters as shown below
eg:
For Mysql : use back codes (`)
Select `columnName ` from `tableName `;
For MSSQL : Use double codes(" or [ ] )
select "columnName" from "tableName"; or
select [columnName] from [tableName];
Note: Before doing this you should sanitize your data with this special characters ( `, " , [ , ] )
I am quite new to Java Sesame and SPARQL. I have added statements into the Sesame repository and am now trying to retrieve some statements and simply print them. From what I understood that I need to parse the query in order to print the retrieved statements. The code below shows where I have reached so far:
String queryString = "SELECT ?subject ?object WHERE { ?subject <http://example.org/is> ?object . } LIMIT 1";
...
SPARQLParser parser = new SPARQLParser();
ParsedQuery query = parser.parseQuery(queryString, null);
StatementPatternCollector collector = new StatementPatternCollector();
query.getTupleExpr().visit(collector);
List<StatementPattern> patterns = collector.getStatementPatterns();
// To print the first statement only for example.
System.out.println(patterns.get(0));
Here is the output:
StatementPattern
Var (name=name)
Var (name=-const-1, value=http://example.org/is, anonymous)
Var (name=object)
According to the output, it does not show me the subject and object. My questions are: How can I print the results of the query as shown above. Is this code the right way to parse the query for printing the statements later. Your help would be very much appreciated.
You get the results of a query by evaluating the query, not by parsing it. What your code does is inspect the query's algebra model and retrieve patterns from that algebra. This approach will not give you query results.
Evaluating a query in Sesame is far simpler than this:
// open a connection to the Sesame repository containing your statements
RepositoryConnection conn = repository.getConnection();
try {
// create a prepared query object from your query string
TupleQuery query = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
// evaluate the query on the repository
TupleQueryResult result = query.evaluate();
// iterate over the results and do something with each result
while (result.hasNext()) {
BindingSet s = result.next();
Value subject = s.getValue("subject");
Value object = s.getValue("object");
System.out.println("value of ?subject: " + subject);
System.out.println("value of ?object: " + object);
}
} finally {
conn.close();
}
As Joshua pointed out, your query retrieves variable bindings (for the variables mentioned in your SELECT clause), not RDF statements. You can of course re-create the RDF statement from those variable bindings in Java, but if you really want full statements rather than just the subject and object, it's probably easier to switch to using a SPARQL CONSTRUCT query instead of a SELECT query.
For more information on how to evaluate different kinds of queries and work with the results in Sesame, see the Sesame user documentation (section 6.5 in particular) and the API Javadoc.
I have follwinig code for search data.
public void advanceSearchMethod(String advanceName, int advanceTpNumber, String advanceAddress, String advanceDescription){
Connection connection=null;
try{
//for connect to database.
connection=(Connection) DriverManager.getConnection("jdbc:mysql://localhost/contactbook","root","time1");
//for communicate with database.
Statement stmt=(Statement)connection.createStatement();
String searchQuery="SELECT * FROM Contacts WHERE Name LIKE '%'"+advanceName+"'%' AND TelePhoneNumber LIKE '"+advanceTpNumber+"%' OR Address LIKE '%'"+advanceAddress+"'%' OR Description LIKE '%'"+advanceDescription+"'%'";
rs=stmt.executeQuery(searchQuery);
contactTableInDefaultForm.setModel(DbUtils.resultSetToTableModel(rs));
}catch(Exception e){
JOptionPane.showMessageDialog(null, "Sorry! Connection Failed");
}
}
No errors in this code.but work catch block. I cannot imagine what I should do. How can I search them?
You have a major bug -- when you build the WHERE clause, you have spurious ' apostrophes after '% opening-quote & wildcard and before %' closing-wildcard & quote.
Your broken code: "WHERE Name LIKE '%'"+advanceName+"'%'"
Corrected: "WHERE Name LIKE '%"+advanceName+"%'"
But the whole code is not good code, at all -- every single thing is wrong with it.
WHERE clauses should be built up only with the conditions you actually need to search on. And should use PreparedStatement and ? bound parameters, rather than building string-literals into the SQL. (You have built a well-known security flaw.)
PhoneNumbers are strings, not integers. The LIKE pattern for TelePhoneNumber doesn't have a starting %.
DB connection should be provided from one class & method, rather than in every method in your application.
Errors in separate operations (getting the connection/ vs. executing the query and reading results) should be checked & reported separately. Exceptions and stacktraces should always be logged (use Log4J) or, at the worst case, output to the console.
The single only thing you got right here, was the variable & parameter naming.
To be honest, you ought to be using Hibernate rather than writing this rickety nonsense.
String searchQuery="SELECT * FROM Contacts WHERE Name LIKE '%'"+advanceName+"'%' AND TelePhoneNumber LIKE '"+advanceTpNumber+"%' OR Address LIKE '%"+advanceAddress+"%' OR Description LIKE '%"+advanceDescription+"%'";
U have added addition single quatation..
Hope this is right answer..
I am using an ORM (ORMlite) and all my calls are going well until I get the following error.
Exception in thread "main" org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "
SELECT * FROM ""STORIES"" WHERE ""TITLE"" = 'Deepcut case leads 'NOT FOLLOWED[*]'' "; SQL statement:
SELECT * FROM Stories WHERE title = 'Deepcut case leads 'not followed'' [42000-152]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:327)
at org.h2.message.DbException.get(DbException.java:167)
at org.h2.message.DbException.get(DbException.java:144)
at org.h2.message.DbException.getSyntaxError(DbException.java:179)
at org.h2.command.Parser.getSyntaxError(Parser.java:480)
at org.h2.command.Parser.prepareCommand(Parser.java:229)
at org.h2.engine.Session.prepareLocal(Session.java:426)
at org.h2.engine.Session.prepareCommand(Session.java:374)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1093)
at org.h2.jdbc.JdbcPreparedStatement.(JdbcPreparedStatement.java:71)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:601)
at com.j256.ormlite.jdbc.JdbcDatabaseConnection.compileStatement(JdbcDatabaseConnection.java:83)
at com.j256.ormlite.stmt.mapped.MappedPreparedStmt.compile(MappedPreparedStmt.java:44)
at com.j256.ormlite.stmt.StatementExecutor.buildIterator(StatementExecutor.java:169)
at com.j256.ormlite.stmt.StatementExecutor.query(StatementExecutor.java:119)
at com.j256.ormlite.dao.BaseDaoImpl.query(BaseDaoImpl.java:189)
I'm confused as to whats going wrong. I am calling the search from these lines:
// get our query builder from the DAO
QueryBuilder<Story, Integer> queryBuilder = StoryDao.queryBuilder();
// the 'title' field must be equal to title (a variable)
queryBuilder.where().eq(Story.TITLE_FIELD_NAME, title);
// prepare our sql statement
PreparedQuery<Story> preparedQuery = queryBuilder.prepare();
// query for all stories that have that title
List<Story> accountList = StoryDao.query(preparedQuery);
Syntax error in SQL statement " SELECT * FROM ""STORIES"" WHERE ""TITLE""...
#bemace is correct that there seem to be quotes in the title that is screwing up the escaping of strings generated by the query.
In ORMLite, you should use the SelectArg feature which will generate a query with SQL ? arguments and then pass the string to the prepared statement directly.
See the documentation on the SelectArg. With it, you'd do something like:
QueryBuilder<Story, Integer> queryBuilder = StoryDao.queryBuilder();
SelectArg titleArg = new SelectArg();
queryBuilder.where().eq(Story.TITLE_FIELD_NAME, titleArg);
PreparedQuery<Story> preparedQuery = queryBuilder.prepare();
titleArg.setValue(title);
List<Story> accountList = StoryDao.query(preparedQuery);
I'm kind of guessing but it looks like there's a problem with the value in the title field, maybe an unescaped quote mark?
I'm not familiar with ORMLite but title = 'Deepcut case leads 'not followed'' doesn't look right. Should probably be "Deepcut case leads 'not followed'" or 'Deepcut case leads \'not followed\'' or some such.
The correct syntax for the statement would be:
SELECT * FROM Stories WHERE title = 'Deepcut case leads ''not followed'' ';
Note the duplicated single quotes inside the string literal.
You will need to tell your ORM layer to follow the ANSI SQL rules for literals.
The exception says that there is some syntactical problem with your generated SELECT statement. Can you print out the generated query? Doing that might help you pin down the exact issue here.
EDIT: Looking closely at your trace shows that string escaping is not handled properly here. Is this your own QueryBuilder? Also, as per this link, are you using SelectArg or directly setting the title?