How to list collections/resources recursivelly in XQuery - recursion

I would like to list all collections from a particular point recursively:
declare function local:list-collections($collection as xs:string) {
for $child in xmldb:get-child-collections($collection)
return
local:list-collections(concat($collection, '/', $child))
};
local:list-collections('/db/apps/tested-bunny/data/')
This returns nothing (no errors, no results). I am inspired by this article and consider it as a good starting point for recursive setting of permissions and so on.

See the dbutil:scan-*() functions in Wolfgang Meier's article on higher order functions with XQuery in eXist-db 2.0+. The article is very instructive article in general. These days the dbutil module is available in the shared-resources package that is installed by default with eXist, so you can make use of it as follows:
xquery version "3.0";
import module namespace dbutil="http://exist-db.org/xquery/dbutil"
at "/db/apps/shared-resources/content/dbutils.xql";
dbutil:scan-collections(
xs:anyURI('/db'),
function($collection) { $collection }
)
These functions perform well. I just ran this in eXide and the query returned 4125 collection names in 0.699s.

Your query does actually recursively find collections, but there is no output. I'd suggest to do something like
declare function local:list-collections($collection as xs:string) {
for $child in xmldb:get-child-collections($collection)
let $childCollection := concat($collection, '/', $child)
return
(local:list-collections($childCollection), $childCollection)
};
local:list-collections('/db/apps/fundocs')
But for sure Joe's suggestion is much cleaner.

Related

BaseX - Out of memory when using enclosing xml in XQuery

I've been trying to query a BaseX db which contains more than 1500000 items.
When i run this query
for $item in collection('coll')//item
return $item (: returns an xml element :)
it executes in less than a second.
But when i try to return the result in an xml I get an "Out of main memory" error.
<xml>{
for $item in collection('coll')//item
return $item
}</xml>
This is something that makes me want to abandon the native xml db approach (same happens with other DBs, such as eXistDB), so if anyone has any info this problem, it would be extremely helpful.
Thanks
Due to the semantics of XQuery, all child nodes need to be copied if they are wrapped by a new parent node. This is demonstrated by the following query, which compares the node identity of the original and copied node. It will yield false:
let $node := <node/>
let $parent := <parent>{ $node }</parent>
return $parent/node is $node
As copying millions of nodes is expensive, this inevitably leads to an out-of-memory error.
If you write results to files, here is a pragmatic solution to get around this restriction:
(:~
: Writes element to a file, wrapped by a root node.
: #param $path path to file
: #param $elements elements to write
: #param $name name of root node
:)
declare function local:write-to(
$path as xs:string,
$elements as element()*,
$name as xs:string
) as empty-sequence() {
file:write-text($path, '<' || $name || '>'),
file:append($path, $elements),
file:append-text($path, '</' || $name || '>')
};
local:write-to('result.xml', <result/>, 'root')
To anticipate criticism: This is a clear hack. For example, the approach conflicts with various non-default serialization parameters of BaseX (the result will not be well-formed if an XML declaration needs to be be output, etc.).
With BaseX 9.0, you can temporarily disable node copying via the COPYNODE option:
(# db:copynode false #) {
<xml>{
for $item in collection('coll')//item
return $item
}</xml>
}

Processing Drupal Node Body

I'm new to Drupal. I looked here and on google for a while before asking, but I'm sure I can't find the answer because I don't know how to ask the question.
Here is what's going on. I'm using a custom module to load certain entities and then output them in a specific format for an application to access. The problem is that the NODE BODY contains special information and media files that should be converted. My goal is to obtain the HTML output that would normally be used on this field.
// Execute an EntityFieldQuery
$result = $query->execute();
if (isset($result['node'])) {
$article_items_nids = array_keys($result['node']);
$article_items = entity_load('node', $news_items_nids);
}
// Loop through each article
foreach ($article_items as $article) {
return $article->body[LANGUAGE_NONE]['0']['value'];
}
All of this works great. The only problem is that I get things like this in the output:
[[{"type":"media","view_mode":"media_original","fid":"283","attributes":{"alt":"","class":"media-image","data-thmr":"thmr_32","height":"400","width":"580"}}]]
or
*protoss_icon*
My goal is to find a way that these items are converted just like they are when these articles are viewed normally.
I've tried doing things such as:
render(field_view_field('node', $article, 'body'));
or
render($article->body[LANGUAGE_NONE]['0']['value']);
without success. Thanks for any help, I'm learning so I don't have a complete grasp of the process drupal uses to build output.
You can try something like this (this works only with nodes not with other custom entity types):
$node = node_load($nid);
$field = field_get_items('node', $node, 'your_field_name');
$output = field_view_value('node', $node, 'your_field_name', $field[$delta]);
the field_view_value returns a renderable array for a single field value. (from drupal api documentation)

Symfony/Doctrine: fetching data as object , still get array

I have in my controller $id it's a foreign key
$query = $em->getRepository('SurgeryPatientBundle:Patients')->findPatientByUserID($id);
And in my repository file this function
public function findPatientByUserID($id)
{
return $this->getEntityManager()
->createQuery('SELECT p FROM SurgeryPatientBundle:Patients p WHERE p.user ='.$id.'')
->execute();
}
I want get an instance of object but still get an array. Query with find($id) works good
edit
Problem solves , I'm so stupid , I had invoked to $query[0]
You can use $query->getSingleResult(); as well
see here
http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html#query-result-formats
If you want to grab the object, you shouldn't be using DQL. Doctrine entities have a find function that takes care of this for you.
Instead of all that code, you can just use (in your controller):
$em->getRepository('SurgeryPatientBundle:Patients')->find($id);
DQL is very powerful, but for simple lookups like this using the built in find methods will be more efficient & provide the entities as doctrine objects.

Drupal: Return SQL string from db_query

Is it possible to return the actual SQL query as a string from the result of db_query?
Or otherwise take the returned resource ID from db_query and get the SQL string?
Edit:
As an addendum, I recently found out about db_queryd() from the Devel module, which echoes the query passed (as well as execute it). Doesn't return the string as this question asked, but really helpful for copying and pasting a complete query.
I don't think it is. However if you are only doing so for the purpose of debugging you can turn on the devel module and that will show you the queries run.
Actually you could just set the variable 'dev_query' to 1 and then access the global array $queries, but I wouldn't recommend it.
Drupal 7, if debug, you could find at \includes\database\database.inc:
function query($query, array $args = array(), $options = array())
$stmt's queryString
or
print_r($stmt->getQueryString());
If you have D7 but don't have Devel to hand, the following snippet could come in useful — it may not handle every type of placeholder however... it currently wrongly assumes all placeholders are strings (which has been fine for my usage).
function stringify_query( $query ){
$s = preg_replace('/\}|\{/', '', $query->__toString());
$a = $query->arguments();
foreach ( $a as $key => $val ) {
$a[$key] = '\'' . $val . '\'';
}
return strtr($s, $a);
}
It also rudely strips out Drupal's curly braces used to handle table prefixes, if you rely on table prefixes then you should find the correct Drupal function to have them replaced correctly.
I would recommend the use of the devel module. There is a setting devel offers which will show all queries run during the generation of a page at the bottom of the page, with data on query execution time and the function that called db_query(). If you have a general idea of what your query will look like or the function that called it, you could search for it within your browser and you can see what was actually send to the database.
Late answer, but you can often turn
$result = db_query($query, $arg1, $arg2);
quickly into
drupal_set_message(sprintf($query, $arg1, $arg2), "status");
And get what you want.
This doesn't help you if you are using an array as your argument to db_query as sprintf doesn't support that, but is often useful in your debugging toolkit.
For those using Drupal 7.x and the Devel module, the correct function to call to output the built SQL statement to the drupal message area is dpq(). It needs to be passed the query object though. e.g.
// to see the built SQL
$query = db_select('node', 'n')->fields('n');
dpq($query);
// to see the results of the query
$results = $query->execute()->fetchAssoc();
dsm($results);
Hope that can help!
D7 version with devel.
>= PHP 5.4
dpm(str_replace(['{', '}'], '', dpq($query, TRUE)));
< PHP 5.4
dpm(str_replace(array('{', '}'), '', dpq($query, TRUE)));

In Drupal, how to change the values passed to Pathauto?

I have Pathauto configured to generate an alias based on the title of a node, for a specific content type. The problem is that I want to make small changes in this title before Pathauto uses it to generate the alias.
The first comment in this post suggests the use of hook_token_values, but I couldn't really understand how to use it, even after reading the docs. In my tests, when I implement this hook, the alias generated is always "array", which means I'm missing something.
Any help? Thanks.
It might be that you missed to implement hook_token_list as well. Providing a new token is a two step process:
Implement hook_token_list to declare the tokens you are going to provide. This will just be the name of the tokens, along with a short explanation, and the information to what type of objects the tokens will apply (e.g. node, user, taxonomy, ...)
Implement hook_token_value to actually generate the content of the tokens. This will be called when the tokens are to be replaced with the content they should stand for.
As you just want to provide an alternative version of the title token already provided by the token module, it is probably best to just copy the relevant portions from token_node.inc, stripped down to the relevant cases and adjusted to be used in another module:
/**
* Implementation of hook_token_list().
*/
function yourModule_token_list($type = 'all') {
if ($type == 'node' || $type == 'all') {
$tokens['node']['yourModule-title'] = t('Node title (customized version by yourModule)');
return $tokens;
}
}
This simply says that yourModule provides a token for node objects, named yourModule-title, along with a short description. The main work gets done in the other hook:
/**
* Implementation of hook_token_values().
*/
function yourModule_token_values($type, $object = NULL, $options = array()) {
$values = array();
switch ($type) {
case 'node':
$node = $object;
// TODO: Replace the check_plain() call with your own token value creation logic!
$values['yourModule-title'] = check_plain($node->title);
break;
}
return $values;
}
This will be called whenever the tokens for node objects are needed, with the node in question being passed as the $object parameter (for a user token, the $type would be 'user', and $object would be the user object, and so on for other types). What it does is creating an array of values, keyed by the token name, with the replacement for that token as the value. The original code from token_node.inc just runs the title through check_plain(), so this would be the place to insert your own logic.
In Drupal 7, the token functionality has been moved to core. Tokens are implemented by the hook_tokens and hook_token_info methods. For usage examples, follow the links provided, and look for links to functions that implement hook_tokens and hook_token_info… I found the statistics_tokens and statistics_token_info functions helpful in understanding how this hook works.
It's probably also worth noting that this hook needs to be implemented by a module… my first attempt I dropped my test functions into the theme's template.php, only to have nothing happen at all :-p

Resources