📄 rdfsource.java
字号:
// optimizations have more effect than the default optimizer QueryOptimizer.optimizeQuery(graphPatternQuery); return; } // Variables used to build the from- and where parts of the SQL query: StringBuffer from = new StringBuffer(512); StringBuffer where = new StringBuffer(256); // Maps Var objects to their ID in SQL, e.g. "t2.subj" Map varToSqlIdMapping = new HashMap(); // List for storing unrecognized path expressions List unknownPathExpressions = new ArrayList(); for (int i = 0; i < pathExpressions.size(); i++) { PathExpression pe = (PathExpression)pathExpressions.get(i); // Assign an ID to this path expression String peId = "t" + i; pe = _convertPathExpressionToSQL(pe, peId, from, where, varToSqlIdMapping); if (pe != null) { // unknown path expression unknownPathExpressions.add(pe); } } if (pathExpressions.size() - unknownPathExpressions.size() <= 1) { // Query contains too few known path expressions for the RDBMS-specific // optimizations have more effect than the default optimizer QueryOptimizer.optimizeQuery(graphPatternQuery); return; } // inline constraints _inlineConstraints(graphPattern, where, varToSqlIdMapping); // Gather variables that need to be exported. This includes: // - variables used in the projection, // - variables used in the remaining boolean constraints, // - variables used in optional child graph expressions, and // - variables used in unkown path expressions // // Variables that are only used in the set of optimized path expressions // are excluded, hence graphPattern.getVariables(Collection) is not used Set varSet = new HashSet(); // - variables used in the projection, graphPatternQuery.getProjectionVariables(varSet); // - variables used in the remaining boolean constraints, BooleanExpr rootConstraint = graphPattern.getRootConstraint(); if (rootConstraint != null) { rootConstraint.getVariables(varSet); } // - variables used in optional child graph expressions, and List optionals = graphPattern.getOptionals(); for (int i = 0; i < optionals.size(); i++) { GraphPattern optionalGP = (GraphPattern)optionals.get(i); optionalGP.getVariables(varSet); } // - variables used in unkown path expressions for (int i = 0; i < unknownPathExpressions.size(); i++) { PathExpression pe = (PathExpression)unknownPathExpressions.get(i); pe.getVariables(varSet); } // Remove variables not present in the optimized path expressions varSet.retainAll( varToSqlIdMapping.keySet() ); // Create an ordered list from the variable set List varList = new ArrayList(varSet); // Create the SQL query: StringBuffer sqlQuery = new StringBuffer(1024); // SELECT clause sqlQuery.append("SELECT "); if (graphPatternQuery.isDistinct()) { sqlQuery.append("DISTINCT "); // We can remove the distinct flag from the GraphPatternQuery if the // entire projection is handled by the SQL query and the if // projection does not contain any value-transforming functions. Set projVarSet = new HashSet(); graphPatternQuery.getProjectionVariables(projVarSet); if (varSet.equals(projVarSet)) { // Entire projection is handled by the SQL query boolean hasTransFunc = false; if (graphPatternQuery instanceof SelectQuery) { ProjectionElem[] projection = ((SelectQuery)graphPatternQuery).getProjection(); for (int i = 0; i < projection.length; i++) { ValueExpr valueExpr = projection[i].getValueExpr(); if (valueExpr instanceof Var || valueExpr instanceof ResourceExpr || valueExpr instanceof LiteralExpr || valueExpr instanceof Null) { // these are OK } else { hasTransFunc = true; break; } } } else if (graphPatternQuery instanceof ConstructQuery) { // All know PathExpression object only use variables, and no // value-transforming functions. } if (!hasTransFunc) { graphPatternQuery.setDistinct(false); } } } for (int i = 0; i < varList.size(); i++) { Var var = (Var)varList.get(i); if (i > 0) { sqlQuery.append(", "); } sqlQuery.append((String)varToSqlIdMapping.get(var)); } // FROM clause; string start with ", ", remove these first 2 characters from.delete(0, 2); sqlQuery.append(" FROM "); sqlQuery.append(from); // WHERE clause if (where.length() > 0) { // where clause starts with " AND ", remove these first 5 characters where.delete(0, 5); sqlQuery.append(" WHERE "); sqlQuery.append(where); } ThreadLog.trace(sqlQuery.toString()); // Create RdbmsPathExpression RdbmsPathExpression rpe = new RdbmsPathExpression( this, _rdbms, varList, sqlQuery.toString()); // Create new list of PathExpression's List newPathExpressions = new ArrayList(1 + unknownPathExpressions.size()); newPathExpressions.add(rpe); newPathExpressions.addAll(unknownPathExpressions); graphPattern.setPathExpressions(newPathExpressions); } /** * Converts a PathExpression to SQL. Table names should be append to * <tt>from</tt>, prefixing the name with the string <tt>", "</tt> and * should be given the name <tt>peId</tt>. Boolean constraints should be * added to <tt>where</tt> and always be prepended with the string * <tt>" AND "</tt> (including spaces). * * @param pathExpr The PathExpression to convert to SQL. * @param peId The ID to use for the path expression in the SQL query. * @param from The from clause. * @param where The where clause. * @param varToSqlIdMapping Mapping of Var objects to their SQL IDs. * * @return <tt>pathExpr</tt> if the path expression could not be * converted, or <tt>null</tt> if it could. */ protected PathExpression _convertPathExpressionToSQL( PathExpression pathExpr, String peId, StringBuffer from, StringBuffer where, Map varToSqlIdMapping) { if (pathExpr instanceof TriplePattern) { TriplePattern tp = (TriplePattern)pathExpr; from.append(", " + TRIPLES_TABLE + " " + peId); _processPathExpressionVar(tp.getSubjectVar(), peId + ".subj", where, varToSqlIdMapping); _processPathExpressionVar(tp.getPredicateVar(), peId + ".pred", where, varToSqlIdMapping); _processPathExpressionVar(tp.getObjectVar(), peId + ".obj", where, varToSqlIdMapping); return null; } else { return pathExpr; } } /** * Processes a path expression variable. A variable with a fixed value will * be assigned this value by adding an equality constraint to the where * clause. A variable that has already been mapped to some other SQL id will * be made equal to this other SQL id. */ protected void _processPathExpressionVar(Var var, String sqlId, StringBuffer where, Map varToSqlIdMapping) { if (var.hasValue()) { int valueId = _getValueId(var.getValue()); //FIXME: what if _getValueId() returned 0? where.append(" AND " + sqlId + " = " + valueId); } else { // Check if variable has been encountered earlier String otherSqlId = (String)varToSqlIdMapping.get(var); if (otherSqlId != null) { where.append(" AND " + sqlId + " = " + otherSqlId); } else { varToSqlIdMapping.put(var, sqlId); } } } /** * Inlines as much of the boolean constraints from * <tt>graphPattern</tt> as possible. */ protected void _inlineConstraints( GraphPattern graphPattern, StringBuffer where, Map varToSqlIdMapping) { boolean constraintsModified = false; List conjunctiveConstraints = new LinkedList( graphPattern.getConjunctiveConstraints()); Iterator iter = conjunctiveConstraints.iterator(); while (iter.hasNext()) { BooleanExpr conjunctiveExpr = (BooleanExpr)iter.next(); String sqlConstraint = _constraintToSql(conjunctiveExpr, varToSqlIdMapping); if (sqlConstraint != null) { where.append(" AND " + sqlConstraint); iter.remove(); constraintsModified = true; } } if (constraintsModified) { graphPattern.setConstraints(conjunctiveConstraints); } } // returns null when the constraint could not be translated to SQL protected String _constraintToSql( BooleanExpr booleanExpr, Map varToSqlIdMapping) { if (booleanExpr instanceof Not) { Not not = (Not)booleanExpr; String argConstraint = _constraintToSql(not.getArg(), varToSqlIdMapping); if (argConstraint != null) { return "NOT(" + argConstraint + ")"; } } else if (booleanExpr instanceof Or) { Or or = (Or)booleanExpr; String leftConstraint = _constraintToSql(or.getLeftArg(), varToSqlIdMapping); String rightConstraint = _constraintToSql(or.getRightArg(), varToSqlIdMapping); if (leftConstraint != null && rightConstraint != null) { return "(" + leftConstraint + " OR " + rightConstraint + ")"; } } else if (booleanExpr instanceof And) { And and = (And)booleanExpr; String leftConstraint = _constraintToSql(and.getLeftArg(), varToSqlIdMapping); String rightConstraint = _constraintToSql(and.getRightArg(), varToSqlIdMapping); if (leftConstraint != null && rightConstraint != null) { return "(" + leftConstraint + " AND " + rightConstraint + ")"; } } else if (booleanExpr instanceof ValueCompare) { ValueCompare valueCompare = (ValueCompare)booleanExpr; // Only inline = and != comparisons if (valueCompare.getOperator() == ValueCompare.EQ || valueCompare.getOperator() == ValueCompare.NE) { ValueExpr leftArg = ((ValueCompare)booleanExpr).getLeftArg(); ValueExpr rightArg = ((ValueCompare)booleanExpr).getRightArg(); // check if one of the arguments is a datatyped literal. // these should not be inlined since type casting may need // to take place. if (leftArg instanceof Literal) { URI leftDt = ((Literal)leftArg).getDatatype(); if (leftDt != null) { return null; } } else if (rightArg instanceof Literal) { URI rightDt = ((Literal)rightArg).getDatatype(); if (rightDt != null) { return null; } } String leftSqlId = null; if (leftArg.getValue() != null) { leftSqlId = String.valueOf(_getValueId(leftArg.getValue())); } else if (leftArg instanceof Var) { leftSqlId = (String)varToSqlIdMapping.get(leftArg); } String rightSqlId = null; if (rightArg.getValue() != null) { rightSqlId = String.valueOf(_getValueId(rightArg.getValue())); } else if (rightArg instanceof Var) { rightSqlId = (String)varToSqlIdMapping.get(rightArg); } if (leftSqlId != null && rightSqlId != null) { if (valueCompare.getOperator() == ValueCompare.EQ) { return leftSqlId + " = " + rightSqlId; } else { return leftSqlId + " <> " + rightSqlId; } } else { return null; } } } return null; } public boolean hasStatement( Resource subj, URI pred, Value obj, boolean explicitOnly) { StringBuffer query = new StringBuffer(200); query.append("SELECT id FROM " + TRIPLES_TABLE); // WHERE clause is not needed if subject, predicate and object are // wildcards and explicitOnly is false. if (subj != null || pred != null || obj != null || explicitOnly) { query.append(" WHERE "); boolean writeAND = false; if (subj != null) { // Subject is specified. int subjId = _getResourceId(subj); if (subjId == 0) { // Resource not found, so statement not present. return false; } query.append("subj = " + subjId); writeAND = true; } if (pred != null) { // Predicate is specified. int predId = _getURIId(pred); if (predId == 0) { // URI not found, so statement not present. return false; } if (writeAND) { query.append(" AND "); } query.append("pred = " + predId); writeAND = true; } if (obj != null) { // Object is specified. int objId = _getValueId(obj); if (objId == 0) { // Resource not found, so statement not present. return false; } if (writeAND) { query.append(" AND "); } query.append("obj = " + objId); writeAND = true; } if (explicitOnly) { if (writeAND) { query.append(" AND "); } query.append("explicit = " + _rdbms.TRUE); } } try { return _rdbms.queryHasResults(query.toString()); } catch (SQLException e) { throw new SailInternalException(e); } } public NamespaceIterator getNamespaces() { if (!_exportStatusUpToDate()) { _updateExportedNamespaces(); } return new RdbmsNamespaceIterator(_namespaceList); }/*-----------------------------------------------------------------------------+| Methods for getting and creating id's for resources, literals and namespaces |+-----------------------------------------------------------------------------*/ /** * Gets the ID of the supplied value. * * @return the ID of the supplied value, or 0 if the value was not found. */ protected int _getValueId(Value value) { if (value instanceof Resource) { return _getResourceId((Resource)value); } else if (value instanceof Literal) { return _getLiteralId((Literal)value); } else { throw new IllegalArgumentException( "parameter 'value' should be of type Resource or Literal"); } } /** * Gets the ID of the supplied resource. * * @return the ID of the supplied resource, or 0 if the resource was not found. */ protected int _getResourceId(Resource res) { if (res instanceof URI) { return _getURIId((URI)res); } else if (res instanceof BNode) { return _getBNodeId((BNode)res); } else { throw new IllegalArgumentException( "parameter 'res' should be of type URI or BNode"); } } /** * Gets the ID of the supplied URI. * * @return the ID of the supplied URI, or 0 if the URI was not found. */ protected int _getURIId(URI uri) { IdURI idURI = null; if (_isOwnValue(uri)) { // ID is possibly stored in the URI object idURI = (IdURI)uri; int id = idURI.getInternalId(); if (id != 0) { return id; } } // Retrieve the ID from the database int result = 0; int nsId = _getNamespaceId(uri.getNamespace()); if (nsId == 0) { // nsId is 0 so uri does not exist. return 0; } String lname = uri.getLocalName(); StringBuffer query = new StringBuffer(150); query.append("SELECT id FROM " + RESOURCES_TABLE); query.append(" WHERE namespace = " + nsId);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -