MarkLogic 8 - XQuery using Document manage and checkout - xquery

I have tried the below mentioned xquery. If document is not managed I want to manage the document using a DLS query otherwise I want to checkout the document.
xquery version "1.0-ml";
import module namespace dls = "http://marklogic.com/xdmp/dls" at "/MarkLogic/dls.xqy";
let $uri :="/root/189966_01.xml"
let $i := dls:document-is-managed($uri)
return
if ($i = fn:false())
then
dls:document-manage($uri, fn:false(), "Baz is now a managed document")
(: dls:document-checkout($uri, fn:true(), "updating doc", 3600) :)
else if ($i = fn:true())
then
dls:document-checkout($uri, fn:true(), "updating doc", 3600)
else
"No action"
please correct me if anything is wrong on my side.

The xquery looks fine. Just a restructuring of the above query -
xquery version "1.0-ml";
import module namespace dls = "http://marklogic.com/xdmp/dls" at "/MarkLogic/dls.xqy";
let $uri :="/root/189966_01.xml"
let $i := dls:document-is-managed($uri)
return
if ($i = fn:false()) then
dls:document-manage($uri, fn:false(), "Baz is now a managed document")
else
if ($i = fn:true()) then
dls:document-checkout($uri, fn:true(), "updating doc", 3600)
else
()

you cannot checkout and manage in the same transaction. You can checkout in 2 independent transactions in the same request, managed by a parent transaction (as long as you do not hold any locks before or during.

Related

exist-db - file:move does not move document

In eXist 4.7 I am trying to move masses of documents into seperate collections.
I build the new target collection dynamically from information in the document (#corresp). So this:
for $doc in collection($globalvar:URIdb)//tei:TEI[#type="exempla"]
let $source := concat("db/apps/thema/data/",
$doc/data(#xml:id),".xml")
let $target := concat("db/apps/thema/data/",
$doc/replace(#corresp,"#",""),
"/",
$doc/data(#xml:id),".xml")
return ($source, $target)
...returns sequences like the following, which are the correct from/to file paths:
db/apps/thema/data/TE001553.xml
db/apps/thema/data/TC0001/TE001553.xml
db/apps/thema/data/TE003403.xml
db/apps/thema/data/TC0001/TE003403.xml
db/apps/thema/data/TE003404.xml
db/apps/thema/data/TC0001/TE003404.xml
But using the function file:move($original as item(), $destination as item()) as xs:boolean:
for $doc in collection($globalvar:URIdb)//tei:TEI[#type="exempla"]
let $source := concat("db/apps/thema/data/",
$doc/data(#xml:id),".xml")
let $target := concat("db/apps/thema/data/",
$doc/replace(#corresp,"#",""),
"/",
$doc/data(#xml:id),".xml")
return file:move($source, $target)
...returns false i.e. no files are moved.
What am I missing in the from/to paths?
Many thanks.

How can I see the SQL generated by SQLite.NET PCL in Xamarin Studio?

I researched this and all I can find is a suggestion to turn on .Trace = true like this:
db1 = DependencyService.Get<ISQLite>().GetConnection();
db1.Trace = true;
I also tried this:
db2.Trace = true;
var categories = db2.Query<Category>("SELECT * FROM Category ORDER BY Name").ToList();
Debug.WriteLine("xxxx");
Well I did this and then restarted the application. When I view the Application output I just see information on threads started and the xxxx but don't see any SQL trace information.
Can anyone give me advice on this. Thanks
You need to set Trace and Tracer (action) properties on your SQLiteConnection to print queries to output:
db.Tracer = new Action<string>(q => Debug.WriteLine(q));
db.Trace = true;
Look in the Application Output window for lines that begin Executing
Example Output after setting Trace to true:
Executing: create table if not exists "Valuation"(
"Id" integer primary key autoincrement not null ,
"StockId" integer ,
"Time" datetime ,
"Price" float )
Executing Query: pragma table_info("Valuation")
Executing: create index if not exists "Valuation_StockId" on "Valuation"("StockId")
Executing: insert into "Stock"("Symbol") values (?)
Executing Query: select * from "Stock" where ("Symbol" like (? || '%'))
0: A
Ref: https://github.com/praeclarum/sqlite-net/blob/38a5ae07c886d6f62cecd8fdeb8910d9b5a77546/src/SQLite.cs
The SQLite PCL uses Debug.WriteLine which means that the logs are only included in Debug builds of the PCL.
Remove your nuget reference to the sqlite.net PCL (leave the native reference), and instead add SQLite.cs as a class to your project, and execute a debug build, with the Trace flag set, and you'll see the tracing.
I didn't have to do anything special other than include the SQLite.cs file in my Xamarin iOS project for this to work:
using (var conn = new SQLite.SQLiteConnection("mydb.sqlite") { Trace = true }) {
var rows = conn.Table<PodcastMetadata>().Where(row => row.DurationMinutes < 10).Select(row => new { row.Title });
foreach (var row in rows) {
Debug.WriteLine(row);
}
}
Output:
Executing Query: select * from "PodcastMetadata" where ("DurationMinutes" < ?)
0: 10

Import data using mlcp, a csv file and transform parse date

I have a csv file. I've managed import these data into MarkLogic using mlcp which then created a xml file in MarkLogic.
Now in csv I have this format "6/29/2013 5:00:00 PM" random in one of the column. How do I use xquery and probably node-replace as a transform function to convert this date into a different format such as "2013-06-29" as MarkLogic default date format?
Any help is appreciated...
I have created transform.xqy and install it on Modules in MLogic. I'm
thinking about using "xdmp:node-replace" to replace the date with expected
format. Or should I go thorugh the csv column by column (How to do?) and
use "castable as xs:dateTime" to determine date value or not. Yet, even
just printing out the content value/uri, always giving me error.
xquery version "1.0-ml";
module namespace example = "http://test.com/example";
(: If the input document is XML, insert #NEWATTR, with the value
: specified in the input parameter. If the input document is not
: XML, leave it as-is.
:)
declare function example:transform(
$content as map:map,
$context as map:map
) as map:map*
{
let $the-doc-uri := map:get($content, "uri")
let $the-doc := map:get($content, "value")
return
trace($the-doc, 'The value of doc is: ')
};
The MarkLogic documentation contains a full example of an MLCP transform:
https://docs.marklogic.com/guide/mlcp/import#id_65640
It shows this example, which adds an attribute to the XML content:
declare function example:transform(
$content as map:map,
$context as map:map
) as map:map*
{
let $attr-value :=
(map:get($context, "transform_param"), "UNDEFINED")[1]
let $the-doc := map:get($content, "value")
return
if (fn:empty($the-doc/element()))
then $content
else
let $root := $the-doc/*
return (
map:put($content, "value",
document {
$root/preceding-sibling::node(),
element {fn:name($root)} {
attribute { fn:QName("", "NEWATTR") } {$attr-value},
$root/#*,
$root/node()
},
$root/following-sibling::node()
}
), $content
)
};
Keep in mind you are supposed to update the "value" property of the $content map:map, and return $content to get your transformation result added to the database. I suggest using a (potentially recursive) typeswitch to identify element nodes, and then adjusting their value accordingly..
HTH!
finally did it.
The thing is I must use mem:node-replace because it is on the fly, on memory. While xdmp:node-replace is when the data is already on MarkLogic.
The rest is as expected I must use format-date and xdmp:parse-dateTime to get date format as required.
Here is some snippets
xquery version "1.0-ml";
module namespace ns_transform = "this_is_my_namespace";
import module namespace mem = "http://xqdev.com/in-mem-update" at "/MarkLogic/appservices/utils/in-mem-update.xqy";
declare variable $ns := "this_is_my_namespace";
declare function ns_transform:transform(
$content as map:map,
$context as map:map
) as map:map*
{
let $doc := map:get($content, "value")
let $format_in := "[M]/[D]/[Y0001] [h01]:[m01]:[s01] [P]"
let $format_out := "[Y0001]-[M01]-[D01]"
let $old_date := $doc/*:root_doc/*:date/text()
let $new_date := format-date(xs:date(xdmp:parse-dateTime($format_in, $old_date)), $format_out)
let $new_doc := mem:node-replace($doc/*:root_doc/*:date,element {fn:QName($ns, "date")}{$new_date})
let $_ := map:put($content, "value", $new_doc)
return $content
};

Converting from Sql to Linq

I have, what I thought was a pretty straight-forward query.
In normal Sql this would read:
SELECT [column names]
FROM agentscheduledetail
WHERE (date = '2012-07-04') AND
(
exception = 'Break (No Sign Off)' OR
exception = 'Break' OR
exception = 'Break (Signed Out)'
)
This returns approx 900 records.
However, when I try to enter this into my controller, I end up with around 300,000 records - so I think my AND and ORs are not working. I've tried Linqer, but can't get it to work (I'm aware this may not be actual LINQ but the equivalent query in VS - if there is a linq version... I'd be grateful for that too if possible).
My controller query is:
var dte = DateTime.Today;
return View(db.agentscheduledetails.Where
(
d => d.date == dte && d.agentName.StartsWith("ta") &&
(
d.exception == "Break (No Sign Off)" ||
d.exception == "Break" ||
d.exception == "Break (Signed Out)"
)
).ToList()
);
Can anyone either a) let me know where I'm going wrong with my && || (and/or), or b) is there a way of stepping through the code in VS, to see what the above query translates to in normal SQL so I can try to figure out where I'm going wrong?
Thanks for any help,
Mark
The following is perhaps a simplified version of what you are trying to do, also your LINQ contains an additional statement compared to the SQL where it is comparing the agent name?
var currentDate = DateTime.Today;
var exceptionTypes = new List<string>() { "Break (No Sign Off)",
"Break", "Break (Signed Out)" };
db.agentscheduledetails.Where(d => d.date == currentDate &&
exceptionTypes.Contains(d.exception));
One thing that you could try is getting hold of a copy of LinqPad, this will let you run your LINQ statement against a database and will show you what the generated SQL statement is.
Aside from anything else,
d.agentName.StartsWith("ta")
does not appear in your original sql...?

NS_ERROR_FILE_IS_LOCKED when several requests using SQLite on Mozilla plateform

I'm trying to use Storage mechanism in Mozilla platform (in thundebird 3.0).
The following code is used after each test to erase the table present in the database:
function tearDown()
{
let database = new Database();
let req1 = "SELECT name FROM sqlite_master WHERE type='table'";
let statement = database.connection.createStatement(req1);
let tables = [];
while(statement.executeStep()) {
tables.push(statement.row.name);
}
statement.reset();
for(table in tables) {
let req2 = "DROP TABLE " + tables[table];
database.connection.executeSimpleSQL(req2);
}
}
But I've an error during executeSimpleSQL of req2 (NS_ERROR_FILE_IS_LOCKED), It seems that SQLite doesn't release the lock from the first statement. I've tried reset(), finalize(), but nothing works. How can I properly release the lock of the first statement?
Answering myself: I forgot to release a previous statement in previous code of my application.
Final story: when you use
statement.executeStep()
Check:
be sure that the last call of this statement return false
or never forgot to release it:
statement.reset();
var statement = dbConn.createStatement("SELECT COUNT(name) AS nameOcurrences FROM Table1 WHERE name = '" + aName + "';");
var occurrences;
while(statement.executeStep()) {
occurrences = statement.row.nameOcurrences;
}

Resources