private void buildXQueryStaticContext(XQueryContext context, boolean importModules) throws XPathException { context.declareNamespaces(namespaceBindings.getCombinedMap()); for (Map.Entry<String, Document> entry : moduleMap.entrySet()) { context.importModule(entry.getKey(), null, "xmldb:exist:///db" + entry.getValue().path()); } }
private org.exist.source.Source buildQuerySource(String query, Object[] params, String cookie) { Map<String, String> combinedMap = namespaceBindings.getCombinedMap(); for (Map.Entry<String, Document> entry : moduleMap.entrySet()) { combinedMap.put("<module> " + entry.getKey(), entry.getValue().path()); } for (Map.Entry<QName, Object> entry : bindings.entrySet()) { combinedMap.put( "<var> " + entry.getKey(), null); // don't care about values, as long as the same vars are bound } combinedMap.put("<posvars> " + params.length, null); combinedMap.put("<cookie>", cookie); // TODO: should include statically known documents and baseURI too? return new StringSourceWithMapKey(query, combinedMap); }
/** * Clone this query service, optionally overriding the clone's namespace and variable bindings. If * the namespace bindings override or variable bindings override is specified, then that object is * cloned and used for its respective purpose. If an override is not specified, the bindings are * cloned from the original query service. * * @param nsBindingsOverride the namespace bindings to clone, or <code>null</code> to clone from * the original * @param varBindingsOverride the variable bindings to clone, or <code>null</code> to clone from * the original * @return a clone of this query service with bindings optionally overridden */ public QueryService clone(NamespaceMap nsBindingsOverride, Map<QName, ?> varBindingsOverride) { try { QueryService that = (QueryService) super.clone(); that.namespaceBindings = nsBindingsOverride != null ? nsBindingsOverride.clone() : that.namespaceBindings.clone(); if (varBindingsOverride == null) { that.bindings = new HashMap<QName, Object>(that.bindings); } else { that.bindings = new HashMap<QName, Object>(); for (Map.Entry<QName, ?> entry : varBindingsOverride.entrySet()) { that.let(entry.getKey(), entry.getValue()); } } that.moduleMap = new TreeMap<String, Document>(moduleMap); return that; } catch (CloneNotSupportedException e) { throw new RuntimeException("unexpected exception", e); } }
boolean isFreshFrom(Resource origin) { return !presub && bindings.isEmpty() && moduleMap.isEmpty() && (namespaceBindings == null || namespaceBindings.isFreshFrom(origin.namespaceBindings())); }
ItemList executeQuery(String query, WrapperFactory wrapperFactory, Object[] params) { long t1 = System.currentTimeMillis(), t2 = 0, t3 = 0, t4 = 0; if (presub) query = presub(query, params); DBBroker broker = null; try { broker = db.acquireBroker(); prepareContext(broker); if (overrideDocs != null) docs = overrideDocs; final org.exist.source.Source source = buildQuerySource(query, params, "execute"); final XQuery xquery = broker.getXQueryService(); final XQueryPool pool = xquery.getXQueryPool(); CompiledXQuery compiledQuery = pool.borrowCompiledXQuery(broker, source); MutableDocumentSet docsToLock = new DefaultDocumentSet(); if (docs != null) docsToLock.addAll(docs); if (base != null) docsToLock.addAll(base.getDocumentSet()); try { XQueryContext context; if (compiledQuery == null) { context = xquery.newContext(AccessContext.INTERNAL_PREFIX_LOOKUP); buildXQueryStaticContext(context, true); } else { context = compiledQuery.getContext(); // static context already set } buildXQueryDynamicContext(context, params, docsToLock, true); t2 = System.currentTimeMillis(); if (compiledQuery == null) { compiledQuery = xquery.compile(context, source); t3 = System.currentTimeMillis(); } docsToLock.lock(broker, false, false); try { return new ItemList( xquery.execute(wrap(compiledQuery, wrapperFactory, context), base), namespaceBindings.extend(), db); } finally { docsToLock.unlock(false); t4 = System.currentTimeMillis(); } } finally { if (compiledQuery != null) pool.returnCompiledXQuery(source, compiledQuery); } } catch (XPathException e) { LOG.debug( "query execution failed -- " + query + " -- " + (params == null ? "" : " with params " + Arrays.asList(params)) + (bindings.isEmpty() ? "" : " and bindings " + bindings)); throw new DatabaseException("failed to execute query", e); } catch (IOException e) { throw new DatabaseException("unexpected exception", e); } catch (LockException e) { throw new DatabaseException("deadlock", e); } catch (PermissionDeniedException e) { throw new DatabaseException("permission denied", e); } finally { db.releaseBroker(broker); STATS.update(query, t1, t2, t3, t4, System.currentTimeMillis()); } }
/** * Declare a namespace binding within the scope of this query. * * @param key the key to bind * @param uri the namespace uri * @return this service, to chain calls */ public QueryService namespace(String key, String uri) { namespaceBindings.put(key, uri); return this; }