Ghislain Fourny has proposed merging lp:~zorba-coders/zorba/bug-1039284 into lp:zorba.
Commit message: Fixes bug 1039284 (json-doc). Requested reviews: Till Westmann (tillw) Matthias Brantner (matthias-brantner) Related bugs: Bug #1039284 in Zorba: "Implement jn:json-doc()" https://bugs.launchpad.net/zorba/+bug/1039284 For more details, see: https://code.launchpad.net/~zorba-coders/zorba/bug-1039284/+merge/129677 Fixes bug 1039284 (json-doc). -- https://code.launchpad.net/~zorba-coders/zorba/bug-1039284/+merge/129677 Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/functions/pregenerated/func_jsoniq_functions.cpp' --- src/functions/pregenerated/func_jsoniq_functions.cpp 2012-10-08 12:09:36 +0000 +++ src/functions/pregenerated/func_jsoniq_functions.cpp 2012-10-15 13:52:21 +0000 @@ -141,6 +141,16 @@ } #endif + +PlanIter_t fn_jsoniq_json_doc::codegen( + CompilerCB*, + static_context* sctx, + const QueryLoc& loc, + std::vector<PlanIter_t>& argv, + expr& ann) const +{ + return new JSONDocIterator(sctx, loc, argv); +} #ifdef ZORBA_WITH_JSON PlanIter_t op_zorba_json_item_accessor::codegen( CompilerCB*, @@ -470,6 +480,18 @@ #endif + + { + DECL_WITH_KIND(sctx, fn_jsoniq_json_doc, + (createQName("http://jsoniq.org/functions","","json-doc"), + GENV_TYPESYSTEM.STRING_TYPE_QUESTION, + GENV_TYPESYSTEM.JSON_ITEM_TYPE_STAR), + FunctionConsts::FN_JSONIQ_JSON_DOC_1); + + } + + + #ifdef ZORBA_WITH_JSON === modified file 'src/functions/pregenerated/func_jsoniq_functions.h' --- src/functions/pregenerated/func_jsoniq_functions.h 2012-10-08 12:09:36 +0000 +++ src/functions/pregenerated/func_jsoniq_functions.h 2012-10-15 13:52:21 +0000 @@ -236,6 +236,25 @@ CODEGEN_DECL(); }; #endif + + +//fn-jsoniq:json-doc +class fn_jsoniq_json_doc : public function +{ +public: + fn_jsoniq_json_doc(const signature& sig, FunctionConsts::FunctionKind kind) + : + function(sig, kind) + { + + } + + bool accessesDynCtx() const { return true; } + + bool isSource() const { return true; } + + CODEGEN_DECL(); +}; #ifdef ZORBA_WITH_JSON //op-zorba:json-item-accessor === modified file 'src/functions/pregenerated/function_enum.h' --- src/functions/pregenerated/function_enum.h 2012-10-08 12:09:36 +0000 +++ src/functions/pregenerated/function_enum.h 2012-10-15 13:52:21 +0000 @@ -240,6 +240,7 @@ FN_JSONIQ_MEMBER_2, FN_JSONIQ_MEMBERS_1, FN_JSONIQ_FLATTEN_1, + FN_JSONIQ_JSON_DOC_1, OP_ZORBA_JSON_ITEM_ACCESSOR_2, FN_JSONIQ_NULL_0, FN_JSONIQ_IS_NULL_1, === modified file 'src/runtime/json/jsoniq_functions_impl.cpp' --- src/runtime/json/jsoniq_functions_impl.cpp 2012-10-08 12:09:36 +0000 +++ src/runtime/json/jsoniq_functions_impl.cpp 2012-10-15 13:52:21 +0000 @@ -46,13 +46,16 @@ #include "types/typeops.h" #include "types/root_typemanager.h" -#include "store/api/pul.h" -#include "store/api/item.h" -#include "store/api/item_factory.h" -#include "store/api/store.h" -#include "store/api/copymode.h" +#include <store/api/pul.h> +#include <store/api/item.h> +#include <store/api/item_factory.h> +#include <store/api/store.h> +#include <store/api/copymode.h> +#include <util/uri_util.h> #include <zorba/store_consts.h> +#include <zorbatypes/URI.h> + namespace zorba { @@ -1597,6 +1600,152 @@ STACK_END(state); } +/** + * Utility method for jn:json-doc(). Given an input string, + * use a few heuristics to create a valid URI, assuming that the input might + * be an absolute or relative filesystem path, etc. + */ +static zstring normalizeInput(zstring const& aUri, static_context* aSctx, + QueryLoc const& loc) +{ + zstring const aBaseUri = aSctx->get_base_uri(); + zstring lResolvedURI; + + try + { + // To support the very common (if technically incorrect) use + // case of users passing local filesystem paths to fn:doc(), + // we use the following heuristic: IF the base URI has a file: + // scheme AND the incoming URI has no scheme, we will assume + // the incoming URI is actually a filesystem path. QQQ For + // the moment, we assume any "unknown" schemes are probably + // Windows drive letters. + if ((uri::get_scheme(aUri) == uri::none || + uri::get_scheme(aUri) == uri::unknown) && + uri::get_scheme(aBaseUri) == uri::file) + { + // Ok, we assume it's a filesystem path. First normalize it. + zstring lNormalizedPath = + fs::get_normalized_path(aUri, zstring("")); + // QQQ For now, get_normalized_path() doesn't do what we + // want when base URI represents a file. So, when the + // normalized path is relative, we pretend it's a relative + // URI and resolve it as such. + if (fs::is_absolute(lNormalizedPath)) + { + URI::encode_file_URI(lNormalizedPath, lResolvedURI); + } + else + { +#ifdef WIN32 + ascii::replace_all(lNormalizedPath, '\\', '/'); +#endif + lResolvedURI = aSctx->resolve_relative_uri(lNormalizedPath, true); + } + } + else + { + // We do NOT assume it's a filesystem path; just resolve it. + lResolvedURI = aSctx->resolve_relative_uri(aUri, true); + } + } + catch (ZorbaException& e) + { + if (e.diagnostic() == err::XQST0046) + // the value of a URILiteral is of nonzero length and is not in the + // lexical space of xs:anyURI. + e.set_diagnostic(err::FODC0005); + else + e.set_diagnostic(err::FODC0002); + + set_source(e, loc); + throw; + } + + return lResolvedURI; +} + +/******************************************************************************* + +********************************************************************************/ +bool JSONDocIterator::nextImpl(store::Item_t& result, PlanState& planState) const +{ + store::Item_t uriItem; + JSONDocIteratorState* state; + zstring uriString; + zstring lErrorMessage; + internal::StreamResource* lStreamResource; + zstring lNormUri; + DEFAULT_STACK_INIT(JSONDocIteratorState, state, planState); + + if (consumeNext(uriItem, theChildren[0].getp(), planState)) + { + uriItem->getStringValue2(uriString); + // Normalize input to handle filesystem paths, etc. + lNormUri = normalizeInput(uriString, theSctx, loc); + + // Resolve URI to a stream + state->theResource = theSctx->resolve_uri( + lNormUri, + internal::EntityData::DOCUMENT, + lErrorMessage); + + lStreamResource = + dynamic_cast<internal::StreamResource*>(state->theResource.get()); + if (lStreamResource == NULL) { + throw XQUERY_EXCEPTION( + err::FODC0002, + ERROR_PARAMS(uriString, lErrorMessage), + ERROR_LOC(loc)); + } + + state->theStream = lStreamResource->getStream(); + if (state->theStream == NULL) { + throw XQUERY_EXCEPTION( + err::FODC0002, + ERROR_PARAMS( uriString ), + ERROR_LOC(loc)); + } + + state->theGotOne = false; + + while (true) + { + try + { + result = GENV_STORE.parseJSON(*state->theStream, 0); + } + catch (zorba::XQueryException& e) + { + // rethrow with JNDY0021 + XQueryException xq = XQUERY_EXCEPTION( + jerr::JNDY0021, + ERROR_PARAMS(e.what()), + ERROR_LOC(loc)); + + // use location of e in case of literal string + throw xq; + } + if (result != NULL) + { + if (!state->theGotOne) + { + state->theGotOne = true; + STACK_PUSH(true, state); + } else { + RAISE_ERROR( + jerr::JNDY0021, + loc, + ERROR_PARAMS(ZED(JSON_UNEXPECTED_EXTRA_CONTENT))); + } + } else { + break; + } + } + } + + STACK_END(state); +} } /* namespace zorba */ /* vim:set et sw=2 ts=2: */ === modified file 'src/runtime/json/pregenerated/jsoniq_functions.cpp' --- src/runtime/json/pregenerated/jsoniq_functions.cpp 2012-10-08 12:09:36 +0000 +++ src/runtime/json/pregenerated/jsoniq_functions.cpp 2012-10-15 13:52:21 +0000 @@ -357,6 +357,46 @@ // </JSONArrayFlattenIterator> #endif +// <JSONDocIterator> +SERIALIZABLE_CLASS_VERSIONS(JSONDocIterator) + +void JSONDocIterator::serialize(::zorba::serialization::Archiver& ar) +{ + serialize_baseclass(ar, + (NaryBaseIterator<JSONDocIterator, JSONDocIteratorState>*)this); +} + + +void JSONDocIterator::accept(PlanIterVisitor& v) const +{ + v.beginVisit(*this); + + std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin(); + std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end(); + for ( ; lIter != lEnd; ++lIter ){ + (*lIter)->accept(v); + } + + v.endVisit(*this); +} + +JSONDocIterator::~JSONDocIterator() {} + +JSONDocIteratorState::JSONDocIteratorState() {} + +JSONDocIteratorState::~JSONDocIteratorState() {} + + +void JSONDocIteratorState::init(PlanState& planState) { + PlanIteratorState::init(planState); +} + +void JSONDocIteratorState::reset(PlanState& planState) { + PlanIteratorState::reset(planState); +} +// </JSONDocIterator> + + #ifdef ZORBA_WITH_JSON // <JSONItemAccessorIterator> SERIALIZABLE_CLASS_VERSIONS(JSONItemAccessorIterator) === modified file 'src/runtime/json/pregenerated/jsoniq_functions.h' --- src/runtime/json/pregenerated/jsoniq_functions.h 2012-10-08 12:09:36 +0000 +++ src/runtime/json/pregenerated/jsoniq_functions.h 2012-10-15 13:52:21 +0000 @@ -29,6 +29,7 @@ #include "runtime/base/binarybase.h" #include "runtime/base/noarybase.h" #include "runtime/base/narybase.h" +#include <context/uri_resolver.h> namespace zorba { @@ -457,6 +458,51 @@ #endif +/** + * jn:json-doc + * Author: Zorba Team + */ +class JSONDocIteratorState : public PlanIteratorState +{ +public: + std::auto_ptr<internal::Resource> theResource; // + std::istream* theStream; // + bool theGotOne; // + + JSONDocIteratorState(); + + ~JSONDocIteratorState(); + + void init(PlanState&); + void reset(PlanState&); +}; + +class JSONDocIterator : public NaryBaseIterator<JSONDocIterator, JSONDocIteratorState> +{ +public: + SERIALIZABLE_CLASS(JSONDocIterator); + + SERIALIZABLE_CLASS_CONSTRUCTOR2T(JSONDocIterator, + NaryBaseIterator<JSONDocIterator, JSONDocIteratorState>); + + void serialize( ::zorba::serialization::Archiver& ar); + + JSONDocIterator( + static_context* sctx, + const QueryLoc& loc, + std::vector<PlanIter_t>& children) + : + NaryBaseIterator<JSONDocIterator, JSONDocIteratorState>(sctx, loc, children) + {} + + virtual ~JSONDocIterator(); + + void accept(PlanIterVisitor& v) const; + + bool nextImpl(store::Item_t& result, PlanState& aPlanState) const; +}; + + #ifdef ZORBA_WITH_JSON /** * === modified file 'src/runtime/pregenerated/iterator_enum.h' --- src/runtime/pregenerated/iterator_enum.h 2012-10-08 12:09:36 +0000 +++ src/runtime/pregenerated/iterator_enum.h 2012-10-15 13:52:21 +0000 @@ -161,6 +161,7 @@ TYPE_JSONArrayMemberIterator, TYPE_JSONArrayMembersIterator, TYPE_JSONArrayFlattenIterator, + TYPE_JSONDocIterator, TYPE_JSONItemAccessorIterator, TYPE_JSONNullIterator, TYPE_JSONIsNullIterator, === modified file 'src/runtime/spec/json/jsoniq_functions.xml' --- src/runtime/spec/json/jsoniq_functions.xml 2012-10-08 12:09:36 +0000 +++ src/runtime/spec/json/jsoniq_functions.xml 2012-10-15 13:52:21 +0000 @@ -9,6 +9,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zorba-xquery.com ../runtime.xsd"> +<zorba:header> + <zorba:include form="Angle-bracket">context/uri_resolver.h</zorba:include> +</zorba:header> + <!-- /******************************************************************************* ********************************************************************************/ @@ -377,6 +381,35 @@ </zorba:iterator> +<!-- +/******************************************************************************* +********************************************************************************/ +--> +<zorba:iterator name="JSONDocIterator"> + + <zorba:description author="Zorba Team">jn:json-doc</zorba:description> + + <zorba:function> + + <zorba:signature localname="json-doc" prefix="fn-jsoniq"> + <zorba:param>xs:string?</zorba:param> + <zorba:output>json-item()*</zorba:output> + </zorba:signature> + + <zorba:methods> + <zorba:accessesDynCtx returnValue="true"/> + <zorba:isSource returnValue="true"/> + </zorba:methods> + + </zorba:function> + + <zorba:state> + <zorba:member type="std::auto_ptr<internal::Resource>" name="theResource" brief=""/> + <zorba:member type="std::istream*" name="theStream" brief=""/> + <zorba:member type="bool" name="theGotOne" brief=""/> + </zorba:state> + +</zorba:iterator> <!-- /******************************************************************************* @@ -659,4 +692,5 @@ </zorba:iterator> + </zorba:iterators> === modified file 'src/runtime/visitors/pregenerated/planiter_visitor.h' --- src/runtime/visitors/pregenerated/planiter_visitor.h 2012-10-08 12:09:36 +0000 +++ src/runtime/visitors/pregenerated/planiter_visitor.h 2012-10-15 13:52:21 +0000 @@ -338,6 +338,8 @@ #ifdef ZORBA_WITH_JSON class JSONArrayFlattenIterator; #endif + class JSONDocIterator; + #ifdef ZORBA_WITH_JSON class JSONItemAccessorIterator; #endif @@ -1188,6 +1190,9 @@ virtual void beginVisit ( const JSONArrayFlattenIterator& ) = 0; virtual void endVisit ( const JSONArrayFlattenIterator& ) = 0; #endif + virtual void beginVisit ( const JSONDocIterator& ) = 0; + virtual void endVisit ( const JSONDocIterator& ) = 0; + #ifdef ZORBA_WITH_JSON virtual void beginVisit ( const JSONItemAccessorIterator& ) = 0; virtual void endVisit ( const JSONItemAccessorIterator& ) = 0; === modified file 'src/runtime/visitors/pregenerated/printer_visitor.cpp' --- src/runtime/visitors/pregenerated/printer_visitor.cpp 2012-10-08 12:09:36 +0000 +++ src/runtime/visitors/pregenerated/printer_visitor.cpp 2012-10-15 13:52:21 +0000 @@ -1973,6 +1973,20 @@ // </JSONArrayFlattenIterator> #endif + +// <JSONDocIterator> +void PrinterVisitor::beginVisit ( const JSONDocIterator& a) { + thePrinter.startBeginVisit("JSONDocIterator", ++theId); + printCommons( &a, theId ); + thePrinter.endBeginVisit( theId ); +} + +void PrinterVisitor::endVisit ( const JSONDocIterator& ) { + thePrinter.startEndVisit(); + thePrinter.endEndVisit(); +} +// </JSONDocIterator> + #ifdef ZORBA_WITH_JSON // <JSONItemAccessorIterator> void PrinterVisitor::beginVisit ( const JSONItemAccessorIterator& a) { === modified file 'src/runtime/visitors/pregenerated/printer_visitor.h' --- src/runtime/visitors/pregenerated/printer_visitor.h 2012-10-08 12:09:36 +0000 +++ src/runtime/visitors/pregenerated/printer_visitor.h 2012-10-15 13:52:21 +0000 @@ -522,6 +522,9 @@ void endVisit ( const JSONArrayFlattenIterator& ); #endif + void beginVisit( const JSONDocIterator& ); + void endVisit ( const JSONDocIterator& ); + #ifdef ZORBA_WITH_JSON void beginVisit( const JSONItemAccessorIterator& ); void endVisit ( const JSONItemAccessorIterator& ); === added file 'test/rbkt/ExpQueryResults/zorba/jsoniq/json_doc_1.xml.res' --- test/rbkt/ExpQueryResults/zorba/jsoniq/json_doc_1.xml.res 1970-01-01 00:00:00 +0000 +++ test/rbkt/ExpQueryResults/zorba/jsoniq/json_doc_1.xml.res 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +{ "foo" : "bar" } === added file 'test/rbkt/ExpQueryResults/zorba/jsoniq/json_doc_2.xml.res' --- test/rbkt/ExpQueryResults/zorba/jsoniq/json_doc_2.xml.res 1970-01-01 00:00:00 +0000 +++ test/rbkt/ExpQueryResults/zorba/jsoniq/json_doc_2.xml.res 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +[ "bar" ] === added file 'test/rbkt/ExpQueryResults/zorba/jsoniq/json_doc_4.xml.res' === added file 'test/rbkt/Queries/zorba/jsoniq/input1.json' --- test/rbkt/Queries/zorba/jsoniq/input1.json 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/input1.json 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +{ "foo" : "bar" } === added file 'test/rbkt/Queries/zorba/jsoniq/input2.json' --- test/rbkt/Queries/zorba/jsoniq/input2.json 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/input2.json 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +{ "foo" : "bar" } { "bar" : "foo" } === added file 'test/rbkt/Queries/zorba/jsoniq/input3.json' --- test/rbkt/Queries/zorba/jsoniq/input3.json 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/input3.json 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +{ "foo" : "bar" } { "bar" : "foo" === added file 'test/rbkt/Queries/zorba/jsoniq/json_doc_1.xq' --- test/rbkt/Queries/zorba/jsoniq/json_doc_1.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/json_doc_1.xq 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +jn:json-doc("input1.json") \ No newline at end of file === added file 'test/rbkt/Queries/zorba/jsoniq/json_doc_2.xq' --- test/rbkt/Queries/zorba/jsoniq/json_doc_2.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/json_doc_2.xq 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +[ jn:json-doc("input1.json")("foo") ] \ No newline at end of file === added file 'test/rbkt/Queries/zorba/jsoniq/json_doc_3.spec' --- test/rbkt/Queries/zorba/jsoniq/json_doc_3.spec 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/json_doc_3.spec 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +Error: http://jsoniq.org/errors:JNDY0021 === added file 'test/rbkt/Queries/zorba/jsoniq/json_doc_3.xq' --- test/rbkt/Queries/zorba/jsoniq/json_doc_3.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/json_doc_3.xq 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +jn:json-doc("input2.json") \ No newline at end of file === added file 'test/rbkt/Queries/zorba/jsoniq/json_doc_4.xq' --- test/rbkt/Queries/zorba/jsoniq/json_doc_4.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/json_doc_4.xq 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +jn:json-doc(()) \ No newline at end of file === added file 'test/rbkt/Queries/zorba/jsoniq/json_doc_5.spec' --- test/rbkt/Queries/zorba/jsoniq/json_doc_5.spec 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/json_doc_5.spec 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +Error: http://jsoniq.org/errors:JNDY0021 === added file 'test/rbkt/Queries/zorba/jsoniq/json_doc_5.xq' --- test/rbkt/Queries/zorba/jsoniq/json_doc_5.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/jsoniq/json_doc_5.xq 2012-10-15 13:52:21 +0000 @@ -0,0 +1,1 @@ +jn:json-doc("input3.json") \ No newline at end of file
-- Mailing list: https://launchpad.net/~zorba-coders Post to : zorba-coders@lists.launchpad.net Unsubscribe : https://launchpad.net/~zorba-coders More help : https://help.launchpad.net/ListHelp