URI works in a SPARQL query, but the Namespace does not - namespaces

I am querying the NIFSTD ontology. I have loaded it into Fuseki, a local triple store/ sparql server.
When querying for the synonyms of the 'hippocampus', the below code with the namespace does not return any answers:
prefix nifstdr: <http://uri.neuinfo.org/nif/nifstd/readable>
prefix rdf: <...>
.
.
SELECT distinct ?s ?synonyms
{?s rdfs:label "Hippocampus" ;
nifstd:synonym ?synonyms .}
While using the URI works and returns correct answers:
prefix rdfs: ...
prefix rdf: ...
SELECT distinct ?s ?synonyms
{?s rdfs:label "Hippocampus" ;
<http://uri.neuinfo.org/nif/nifstd/readable/synonym> ?synonyms .}
Another similar (but opposite) instance to this one was when I was querying the local graph for IDs of the concepts as below:
PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
select distinct ?id
where{
graph <http://localhost:3030/myDataset/data/nif>{
?s oboInOwl:id ?id.
}
}
limit 100
This code returned results.
However, using URI within the code as below, returned no results at all!
select distinct ?id
where{
graph <http://localhost:3030/myDataset/data/nif>{
?s <http://www.geneontology.org/formats/oboInOwl/id> ?id.
}
}
limit 100
So, this time it was the other way around!
I thought maybe this is because the local triple store has a URI that I previously used for this dataset in its cache, so I gave it a different name, but the problem still persists.
Why does this happen?

In the updated question,
The full URI in the query is http://www.geneontology.org/formats/oboInOwl/id
but oboInOwl:id expands to a different URI: http://www.geneontology.org/formats/oboInOwl#id
The difference is the #-/ .
nifstd:synonym becomes http://uri.neuinfo.org/nif/nifstd/readablesynomyn not .../readable/synomyn.

Related

Translate SPARQL to SQL

I would like to know if there is a way to obtain the SQL query starting from a SPARQL query.
For example, I have this SPARQL query:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX ub: <http://www.lehigh.edu/~zhp2/2004/0401/univ-bench.owl#>
SELECT ?X
WHERE {
?X rdf:type ub:GraduateStudent .
?X ub:takesCourse <http://www.Department0.University0.edu/GraduateCourse0>
}
I would like to obtain something like this (the triples are stored in a table triples(subject, predicate, object):
SELECT subject
FROM triples
WHERE predicate = "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>"
AND object = "<http://swat.cse.lehigh.edu/onto/univ-bench.owl#GraduateStudent>"
AND subject IN (
SELECT subject
FROM triples
WHERE predicate = "<http://swat.cse.lehigh.edu/onto/univ-bench.owl#takesCourse>"
AND object = "<http://www.Department0.University0.edu/GraduateCourse0>"
)
or
SELECT subject
FROM triples
WHERE predicate = "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>"
AND object = "<http://swat.cse.lehigh.edu/onto/univ-bench.owl#GraduateStudent>"
INTERSECT
SELECT subject
FROM triples
WHERE predicate = "<http://swat.cse.lehigh.edu/onto/univ-bench.owl#takesCourse>"
AND object = "<http://www.Department0.University0.edu/GraduateCourse0>"
Thank you in advance!
Apache Jena used to provide SQL storage : see https://github.com/apache/jena/tree/main/jena-sdb on how to get the old code. It translates basic graph patterns using JOIN and OPTIONAL with LEFT JOIN.
It has its own database layout with RDF terms in a dictionary. There was also a simple scheme with strings and a single triples table - that is not efficient in practice. See also the very old "RDB" Jena storage which was in the pre-Apache project.
There are also various papers on the web discussing this topic.

SQL injection with no spaces

I'm trying to exploit an SQL injection on a website (in the name of Science, of course). After some tests I found how the back-end works. The SQL query is formed like this:
$query = 'SELECT * FROM TABLE WHERE ID ='.$segment
where $segment is the second path segment from the URL. In case of http://vict.im/menu/10 it equals 10. Symbols /, # and everything after them is ignored, so the previous link, http://vict.im/menu/10/blah-blah and http://vict.im/menu/10#blah-blah give the same result.
The problem here is that the segment-parser doesn't URLdecode() the segment. If I send .../menu/30 ; it will be encoded to .../menu/30%20;, and MySQL will interpret it as remainder of division, returning us result where ID = 10. By the same reason + is not replaced for whitespace, it works as an operator.
So, it's needed to make an injection that doesn't contain any symbols usually encoded by web browsers. For example, .../menu/(10)or(1=1), boolean-based injection .../menu/9+(USER()='Smith') and .../menu/CONCAT('1','0') work fine.
How can I explain this situation to Sqlmap? Is there a tamper script for this? Are there any other ways to bypass this "protection"?
P.S. It seems following symbols can be used: ! $ & ' ( ) * + , : ; = ? # [ ] plus mixalpha-numeric.

Spring data Couchbase #n1ql.fields query

I'm trying to make a N1QL based query on Spring Data Couchbase. The documentation says
#n1ql.fields will be replaced by the list of fields (eg. for a SELECT clause) necessary to reconstruct the entity.
My repository implementation is this one:
#Query("#{#n1ql.fields} WHERE #{#n1ql.filter}")
List<User> findAllByFields(String fields);
And I'm calling this query as follows:
this.userRepository.findAllByFields("SELECT firstName FROM default");
I'm getting this error:
Caused by: org.springframework.data.couchbase.core.CouchbaseQueryExecutionException: Unable to execute query due to the following n1ql errors:
{"msg":"syntax error - at AS","code":3000}
After a little bit of researching, I also tryed:
#Query("SELECT #{#n1ql.fields} FROM #{#n1ql.bucket} WHERE #{#n1ql.filter}")
With this query, I don't get an error, I get all the documents stored but only the ID the other fields are set to null, when my query tries to get the firstName field.
this.userRepository.findAllByFields("firstName");
Anyone knows how to do such a query?
Thank you in advance.
You're misunderstanding the concept, I encourage you to give the documentation more time and see more examples. I'm not sure what exactly you're trying to achieve but I'll throw some examples.
Find all users (with all of their stored data)
#Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter}")
List<User> findAllUsers();
This will basically generate SELECT meta().id,_cas,* FROM bucket WHERE type='com.example.User'
Notice findAllUsers() does not take any parameters because there are no param placeholders defined in the #Query above.
Find all users where firstName like
#Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND firstName like $1")
List<User> findByFirstNameLike(String keyword);
This will generate something like the above query but with an extra where condition firstName like
Notice this method takes a keyword because there is a param placeholder defined $1.
Notice in the documentation it says
#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND test = $1
is equivalent to
SELECT #{#n1ql.fields} FROM #{#n1ql.bucket} WHERE
#{#n1ql.filter} AND test = $1
Now if you don't want to fetch all the data for user(s), you'll need to specify the fields being selected, read following links for more info
How to fetch a field from document using n1ql with spring-data-couchbase
https://docs.spring.io/spring-data/couchbase/docs/2.2.4.RELEASE/reference/html/#_dto_projections
I think you should try below query, that should resolve the issue to get fields based parameter you have sent as arguments.
Please refer blow query.
#Query("SELECT $1 FROM #{#n1q1.bucket} WHERE #{#n1ql.filter}")
List findByFirstName(String fieldName);
Here, bucket name resolve to the User entity and and n1ql.filter would be a default filter.

Optimal way to find similar value from a large table

I have a database where i am storing more than 1000000 names in mysql. Now the task of my application is a bit typical. I not only searches for names in the database,but also finds similar names. Suppose the name is entered as christian, then the application will show suggested names like christine, chris etc. What is the optimal way to do this, without using the like clause. The suggestions will be only on the changes in the last part of the name.
If you want also similar names (by sound) something like SOUNDEX() could help: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_soundex
Otherwise … LIKE 'chri%' seems for me not a bad idea?
If you really want just the first characters without LIKE you can use SUBSTRING().
You could use php's metaphone() function to generate the metaphone-code for each name and store them along with the names.
<?php
print "chris" . "\t" . metaphone("chris") . "\n";
print "christian" . "\t" . metaphone("christian") . "\n";
print "christine" . "\t" . metaphone("christine") . "\n";
# prints:
# chris XRS
# christine XRSTN
# christian XRSXN
You can then use a levenshtein distance algorithm (either in php [http://php.net/manual/en/function.levenshtein.php] or mysql [http://www.artfulsoftware.com/infotree/queries.php#552]) to calculate the distance between the metacodes. In my test below a distance of 2 or less seemed to indicate the level of similarity that you are seeking.
<?php
$names = array(
array('mike',metaphone('mike')),
array('chris',metaphone('chris')),
array('chrstian',metaphone('christian')),
array('christine',metaphone('christine')),
array('michelle',metaphone('chris')),
array('mick',metaphone('mick')),
array('john',metaphone('john')),
array('joseph',metaphone('joseph'))
);
foreach ($names as $name) {
_compare($name);
}
function _compare($n) {
global $names;
$name = $n[0];
$meta = $n[1];
foreach ($names as $cname) {
printf("The distance between $name and {$cname[0]} is %d\n",
levenshtein($meta, $cname[1]));
}
}
Like is generally a good solution, but another way to improve performance for this might be to create a partial column index and then submit queries at the same length as your prefix. See the MySQL documentation regarding col_name(length).
You could use a regular experssion i think. I'm not goot at thme but there is a function called REGEXP that you can put in a WHERE clause. Look here
You can use SOUNDS LIKE, I think it should be quite fast as well.
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#operator_sounds-like
Using LIKE where the left hand side is fixed won't require a table scan. I'm assuming this is why you don't want to use LIKE : SELECT * FROM table WHERE name LIKE CONCAT(?, "%") is fast and won't require a table scan to find rows. The CONCAT allows you to use prepared queries with % syntax.
You could also do something like:
SELECT * from table WHERE name < 'christian' LIMIT 20
and
SELECT * FROM table WHERE name > 'christian' LIMIT 20
to find neighbors in the sorted list.

Using enum in drupal

I have a mysql table id,name,gender,age religion( enum('HIN','CHR','MUS') ,category(enum('IND','AMR','SPA') where last 2 are enum datatype and my code in drupal was
$sql="SELECT * FROM {emp} WHERE age=".$age." and religion=".$rel." and category=".$categ;
$result=db_query_range($sql,0,10);
while($data=db_fetch_object($result))
{
print $data->id." ".$data->name."<br>";
}
I get no result or error . I'm trying different query with each field and all are fine except using enum.
for ex: $sql='SELECT * FROM {emp} WHERE religion="'.$rel.'"';
Is there any problem in using enum datatype in drupal
Enum is not something that I believe drupal can make with the schema API, which is what you in most cases want to use for modules and stuff. Also you are lacking an ending ) in your reference to it, but I'm sure you did it right when your made the table.
Enum is only a constraint that is built into the database when inserting values. So if you try to insert an invalid value, you will insert an empty string instead. So it wont have any effect on Drupal querying to get data. It also wont have any effect when Drupal insert values, other than converting invalid values to empty strings. You might want to check the your data, to see if it is as expected. You might just get no results because your query doesn't match anything.
Another thing is the way you construct your queries is a big NO NO, as it's very insecure. What you should do is this:
db_query("SELECT ... '%s' ...", $var);
Drupal will replace %s with your var and make sure there is no SQL injection and other nasty things. %s indicates the var is a string, use %d for ints and there are a few others I can't remember just now. You can have several placeholders like this, and they will be insert in order, much like the t function.
Seconding Googletorps advise on using parameterized queries (+1). That would not only be more secure, but also make it easier to spot the errors ;)
Your original query misses some quotes around your (String) comparison values. The following should work (Note the added single quotes):
$sql = "SELECT * FROM {emp} WHERE age='" . $age . "' and religion='" . $rel . "' and category='" . $categ . "'";
The right way to do it would be something like this:
$sql = "SELECT * FROM {emp} WHERE age='%s' and religion='%s' and category='%s'";
$args = array($age, $rel, $categ);
$result = db_query_range($sql, $args ,0 , 10);
// ...