Strabon

changeset 407:b0045954fe02

Altered behavior for datetime values, motivated by NOA use case.
The LEFT JOIN with datetime_values is now placed right after the INNER JOIN
with the predicate table involving temporal values.

This changeset has only been tested so far with temporal selections such as

FILTER(\"2007-08-25T20:00:00\"^^xsd:dateTime <= ?HAT
&& ?HAT < \"2007-08-25T21:00:00\"^^xsd:dateTime).

Testing for cases such as temporal joins that involve values from multiple predicate tables
should follow.

Finally, GeneralDBBooleanExprFactory now contains (commented) code that can be used to
remove MOD expressions from the evaluation of datetime values if deemed appropriate
author Manos Karpathiotakis <mk@di.uoa.gr>
date Thu Jul 05 17:05:31 2012 +0300 (2012-07-05)
parents 980bb71b7d05
children 088dc9156bb8
files generaldb/src/main/java/org/openrdf/sail/generaldb/algebra/factories/GeneralDBBooleanExprFactory.java generaldb/src/main/java/org/openrdf/sail/generaldb/evaluation/GeneralDBSqlJoinBuilder.java generaldb/src/main/java/org/openrdf/sail/generaldb/optimizers/GeneralDBValueJoinOptimizer.java
line diff
     1.1 --- a/generaldb/src/main/java/org/openrdf/sail/generaldb/algebra/factories/GeneralDBBooleanExprFactory.java	Tue Jul 03 19:02:28 2012 +0300
     1.2 +++ b/generaldb/src/main/java/org/openrdf/sail/generaldb/algebra/factories/GeneralDBBooleanExprFactory.java	Thu Jul 05 17:05:31 2012 +0300
     1.3 @@ -148,8 +148,8 @@
     1.4  	private GeneralDBSqlExprFactory sql;
     1.5  
     1.6  	public GeneralDBSqlExpr createBooleanExpr(ValueExpr expr)
     1.7 -	throws UnsupportedRdbmsOperatorException
     1.8 -	{
     1.9 +			throws UnsupportedRdbmsOperatorException
    1.10 +			{
    1.11  		result = null;
    1.12  		if (expr == null)
    1.13  			return new GeneralDBSqlNull();
    1.14 @@ -157,21 +157,21 @@
    1.15  		if (result == null)
    1.16  			return new GeneralDBSqlNull();
    1.17  		return result;
    1.18 -	}
    1.19 +			}
    1.20  
    1.21  	@Override
    1.22  	public void meet(And node)
    1.23 -	throws UnsupportedRdbmsOperatorException
    1.24 -	{
    1.25 +			throws UnsupportedRdbmsOperatorException
    1.26 +			{
    1.27  		result = and(bool(node.getLeftArg()), bool(node.getRightArg()));
    1.28 -	}
    1.29 +			}
    1.30  
    1.31  	@Override
    1.32  	public void meet(Bound node)
    1.33 -	throws UnsupportedRdbmsOperatorException
    1.34 -	{
    1.35 +			throws UnsupportedRdbmsOperatorException
    1.36 +			{
    1.37  		result = not(isNull(new GeneralDBRefIdColumn(node.getArg())));
    1.38 -	}
    1.39 +			}
    1.40  
    1.41  
    1.42  	/**
    1.43 @@ -180,8 +180,8 @@
    1.44  	 */
    1.45  	@Override
    1.46  	public void meet(Compare compare)
    1.47 -	throws UnsupportedRdbmsOperatorException
    1.48 -	{
    1.49 +			throws UnsupportedRdbmsOperatorException
    1.50 +			{
    1.51  		ValueExpr left = compare.getLeftArg();
    1.52  		ValueExpr right = compare.getRightArg();
    1.53  		CompareOp op = compare.getOperator();
    1.54 @@ -313,7 +313,13 @@
    1.55  				GeneralDBSqlExpr within = cmp(time(left), op, sub(time(right), num(HR14)));
    1.56  				GeneralDBSqlExpr comp = or(eq(zoned(left), zoned(right)), within);
    1.57  				GeneralDBSqlExpr dateTime = and(eq(type(left), type(right)), and(comp, time));
    1.58 +				/**
    1.59 +				 * In case you need to remove the operations involving MOD,
    1.60 +				 * use the following line for datetime instead:
    1.61 +				 */
    1.62 +//				GeneralDBSqlExpr dateTime = and(eq(type(left), type(right)), time);
    1.63  				result = or(cmp(numeric(left), op, numeric(right)), or(dateTime, labels));
    1.64 +
    1.65  			}
    1.66  			else
    1.67  			{
    1.68 @@ -332,41 +338,41 @@
    1.69  
    1.70  			break;
    1.71  		}
    1.72 -	}
    1.73 +			}
    1.74  
    1.75  	@Override
    1.76  	public void meet(IsBNode node)
    1.77 -	throws UnsupportedRdbmsOperatorException
    1.78 -	{
    1.79 +			throws UnsupportedRdbmsOperatorException
    1.80 +			{
    1.81  		result = isNotNull(sql.createBNodeExpr(node.getArg()));
    1.82 -	}
    1.83 +			}
    1.84  
    1.85  	@Override
    1.86  	public void meet(IsLiteral node)
    1.87 -	throws UnsupportedRdbmsOperatorException
    1.88 -	{
    1.89 +			throws UnsupportedRdbmsOperatorException
    1.90 +			{
    1.91  		result = isNotNull(sql.createLabelExpr(node.getArg()));
    1.92 -	}
    1.93 +			}
    1.94  
    1.95  	@Override
    1.96  	public void meet(IsResource node)
    1.97 -	throws UnsupportedRdbmsOperatorException
    1.98 -	{
    1.99 +			throws UnsupportedRdbmsOperatorException
   1.100 +			{
   1.101  		GeneralDBSqlExpr isBNode = isNotNull(sql.createBNodeExpr(node.getArg()));
   1.102  		result = or(isBNode, isNotNull(sql.createUriExpr(node.getArg())));
   1.103 -	}
   1.104 +			}
   1.105  
   1.106  	@Override
   1.107  	public void meet(IsURI node)
   1.108 -	throws UnsupportedRdbmsOperatorException
   1.109 -	{
   1.110 +			throws UnsupportedRdbmsOperatorException
   1.111 +			{
   1.112  		result = isNotNull(sql.createUriExpr(node.getArg()));
   1.113 -	}
   1.114 +			}
   1.115  
   1.116  	@Override
   1.117  	public void meet(LangMatches node)
   1.118 -	throws UnsupportedRdbmsOperatorException
   1.119 -	{
   1.120 +			throws UnsupportedRdbmsOperatorException
   1.121 +			{
   1.122  		ValueExpr left = node.getLeftArg();
   1.123  		ValueExpr right = node.getRightArg();
   1.124  		GeneralDBSqlCase sqlCase = new GeneralDBSqlCase();
   1.125 @@ -374,33 +380,33 @@
   1.126  		GeneralDBSqlExpr pattern = concat(lowercase(label(right)), str("%"));
   1.127  		sqlCase.when(new GeneralDBTrueValue(), like(label(left), pattern));
   1.128  		result = sqlCase;
   1.129 -	}
   1.130 +			}
   1.131  
   1.132  	@Override
   1.133  	public void meet(Not node)
   1.134 -	throws UnsupportedRdbmsOperatorException
   1.135 -	{
   1.136 +			throws UnsupportedRdbmsOperatorException
   1.137 +			{
   1.138  		result = not(bool(node.getArg()));
   1.139 -	}
   1.140 +			}
   1.141  
   1.142  	@Override
   1.143  	public void meet(Or node)
   1.144 -	throws UnsupportedRdbmsOperatorException
   1.145 -	{
   1.146 +			throws UnsupportedRdbmsOperatorException
   1.147 +			{
   1.148  		result = or(bool(node.getLeftArg()), bool(node.getRightArg()));
   1.149 -	}
   1.150 +			}
   1.151  
   1.152  	@Override
   1.153  	public void meet(Regex node)
   1.154 -	throws UnsupportedRdbmsOperatorException
   1.155 -	{
   1.156 +			throws UnsupportedRdbmsOperatorException
   1.157 +			{
   1.158  		result = regex(label(node.getArg()), label(node.getPatternArg()), label(node.getFlagsArg()));
   1.159 -	}
   1.160 +			}
   1.161  
   1.162  	@Override
   1.163  	public void meet(SameTerm node)
   1.164 -	throws UnsupportedRdbmsOperatorException
   1.165 -	{
   1.166 +			throws UnsupportedRdbmsOperatorException
   1.167 +			{
   1.168  		ValueExpr left = node.getLeftArg();
   1.169  		ValueExpr right = node.getRightArg();
   1.170  		boolean leftIsVar = left instanceof Var;
   1.171 @@ -423,132 +429,132 @@
   1.172  			GeneralDBSqlExpr literals = and(langs, and(datatype, labels));
   1.173  			result = and(bnodes, and(uris, literals));
   1.174  		}
   1.175 -	}
   1.176 +			}
   1.177  
   1.178  	@Override
   1.179  	public void meet(ValueConstant vc)
   1.180 -	throws UnsupportedRdbmsOperatorException
   1.181 -	{
   1.182 +			throws UnsupportedRdbmsOperatorException
   1.183 +			{
   1.184  		result = valueOf(vc.getValue());
   1.185 -	}
   1.186 +			}
   1.187  
   1.188  	@Override
   1.189  	public void meet(Var var)
   1.190 -	throws UnsupportedRdbmsOperatorException
   1.191 -	{
   1.192 +			throws UnsupportedRdbmsOperatorException
   1.193 +			{
   1.194  		if (var.getValue() == null) {
   1.195  			result = effectiveBooleanValue(var);
   1.196  		}
   1.197  		else {
   1.198  			result = valueOf(var.getValue());
   1.199  		}
   1.200 -	}
   1.201 +			}
   1.202  
   1.203  	public void setSqlExprFactory(GeneralDBSqlExprFactory sql) {
   1.204  		this.sql = sql;
   1.205  	}
   1.206  
   1.207  	protected GeneralDBSqlExpr bNode(ValueExpr arg)
   1.208 -	throws UnsupportedRdbmsOperatorException
   1.209 -	{
   1.210 +			throws UnsupportedRdbmsOperatorException
   1.211 +			{
   1.212  		return sql.createBNodeExpr(arg);
   1.213 -	}
   1.214 +			}
   1.215  
   1.216  	protected GeneralDBSqlExpr bool(ValueExpr arg)
   1.217 -	throws UnsupportedRdbmsOperatorException
   1.218 -	{
   1.219 +			throws UnsupportedRdbmsOperatorException
   1.220 +			{
   1.221  		return sql.createBooleanExpr(arg);
   1.222 -	}
   1.223 +			}
   1.224  
   1.225  	protected GeneralDBSqlExpr label(ValueExpr arg)
   1.226 -	throws UnsupportedRdbmsOperatorException
   1.227 -	{
   1.228 +			throws UnsupportedRdbmsOperatorException
   1.229 +			{
   1.230  		return sql.createLabelExpr(arg);
   1.231 -	}
   1.232 +			}
   1.233  
   1.234  	protected GeneralDBSqlExpr lang(ValueExpr arg)
   1.235 -	throws UnsupportedRdbmsOperatorException
   1.236 -	{
   1.237 +			throws UnsupportedRdbmsOperatorException
   1.238 +			{
   1.239  		return sql.createLanguageExpr(arg);
   1.240 -	}
   1.241 +			}
   1.242  
   1.243  	protected GeneralDBSqlExpr hash(ValueExpr arg)
   1.244 -	throws UnsupportedRdbmsOperatorException
   1.245 -	{
   1.246 +			throws UnsupportedRdbmsOperatorException
   1.247 +			{
   1.248  		return sql.createHashExpr(arg);
   1.249 -	}
   1.250 +			}
   1.251  
   1.252  	@Override
   1.253  	protected void meetNode(QueryModelNode arg)
   1.254 -	throws UnsupportedRdbmsOperatorException
   1.255 -	{
   1.256 +			throws UnsupportedRdbmsOperatorException
   1.257 +			{
   1.258  		if (arg instanceof ValueExpr) {
   1.259  			result = effectiveBooleanValue((ValueExpr)arg);
   1.260  		}
   1.261  		else {
   1.262  			throw unsupported(arg);
   1.263  		}
   1.264 -	}
   1.265 +			}
   1.266  
   1.267  	protected GeneralDBSqlExpr numeric(ValueExpr arg)
   1.268 -	throws UnsupportedRdbmsOperatorException
   1.269 -	{
   1.270 +			throws UnsupportedRdbmsOperatorException
   1.271 +			{
   1.272  		return sql.createNumericExpr(arg);
   1.273 -	}
   1.274 +			}
   1.275  
   1.276  	protected GeneralDBSqlExpr time(ValueExpr arg)
   1.277 -	throws UnsupportedRdbmsOperatorException
   1.278 -	{
   1.279 +			throws UnsupportedRdbmsOperatorException
   1.280 +			{
   1.281  		return sql.createTimeExpr(arg);
   1.282 -	}
   1.283 +			}
   1.284  
   1.285  	protected GeneralDBSqlExpr type(ValueExpr arg)
   1.286 -	throws UnsupportedRdbmsOperatorException
   1.287 -	{
   1.288 +			throws UnsupportedRdbmsOperatorException
   1.289 +			{
   1.290  		return sql.createDatatypeExpr(arg);
   1.291 -	}
   1.292 +			}
   1.293  
   1.294  	protected GeneralDBSqlExpr uri(ValueExpr arg)
   1.295 -	throws UnsupportedRdbmsOperatorException
   1.296 -	{
   1.297 +			throws UnsupportedRdbmsOperatorException
   1.298 +			{
   1.299  		return sql.createUriExpr(arg);
   1.300 -	}
   1.301 +			}
   1.302  
   1.303  	protected GeneralDBSqlExpr zoned(ValueExpr arg)
   1.304 -	throws UnsupportedRdbmsOperatorException
   1.305 -	{
   1.306 +			throws UnsupportedRdbmsOperatorException
   1.307 +			{
   1.308  		return sql.createZonedExpr(arg);
   1.309 -	}
   1.310 +			}
   1.311  
   1.312  	private GeneralDBSqlExpr effectiveBooleanValue(ValueExpr v)
   1.313 -	throws UnsupportedRdbmsOperatorException
   1.314 -	{
   1.315 +			throws UnsupportedRdbmsOperatorException
   1.316 +			{
   1.317  		String bool = XMLSchema.BOOLEAN.stringValue();
   1.318  		GeneralDBSqlCase sqlCase = new GeneralDBSqlCase();
   1.319  		sqlCase.when(eq(type(v), str(bool)), eq(label(v), str("true")));
   1.320  		sqlCase.when(simple(type(v)), not(eq(label(v), str(""))));
   1.321  		sqlCase.when(isNotNull(numeric(v)), not(eq(numeric(v), num(0))));
   1.322  		return sqlCase;
   1.323 -	}
   1.324 +			}
   1.325  
   1.326  	private GeneralDBSqlExpr equal(ValueExpr left, ValueExpr right)
   1.327 -	throws UnsupportedRdbmsOperatorException
   1.328 -	{
   1.329 +			throws UnsupportedRdbmsOperatorException
   1.330 +			{
   1.331  		GeneralDBSqlExpr bnodes = eq(bNode(left), bNode(right));
   1.332  		GeneralDBSqlExpr uris = eq(uri(left), uri(right));
   1.333  		GeneralDBSqlCase scase = new GeneralDBSqlCase();
   1.334  		scase.when(or(isNotNull(bNode(left)), isNotNull(bNode(right))), bnodes);
   1.335  		scase.when(or(isNotNull(uri(left)), isNotNull(uri(right))), uris);
   1.336  		return literalEqual(left, right, scase);
   1.337 -	}
   1.338 +			}
   1.339  
   1.340  	private boolean isTerm(ValueExpr node) {
   1.341  		return node instanceof Var || node instanceof ValueConstant;
   1.342  	}
   1.343  
   1.344  	private GeneralDBSqlExpr literalEqual(ValueExpr left, ValueExpr right, GeneralDBSqlCase scase)
   1.345 -	throws UnsupportedRdbmsOperatorException
   1.346 -	{
   1.347 +			throws UnsupportedRdbmsOperatorException
   1.348 +			{
   1.349  		GeneralDBSqlExpr labels = eq(label(left), label(right));
   1.350  		GeneralDBSqlExpr langs = and(eqIfNotNull(lang(left), lang(right)), labels.clone());
   1.351  		GeneralDBSqlExpr numeric = eq(numeric(left), numeric(right));
   1.352 @@ -564,18 +570,18 @@
   1.353  		scase.when(comparable, time);
   1.354  		scase.when(and(eq(type(left), type(right)), labels.clone()), new GeneralDBTrueValue());
   1.355  		return scase;
   1.356 -	}
   1.357 +			}
   1.358  
   1.359  	private GeneralDBSqlExpr termsEqual(ValueExpr left, ValueExpr right)
   1.360 -	throws UnsupportedRdbmsOperatorException
   1.361 -	{
   1.362 +			throws UnsupportedRdbmsOperatorException
   1.363 +			{
   1.364  		GeneralDBSqlExpr bnodes = eqIfNotNull(bNode(left), bNode(right));
   1.365  		GeneralDBSqlExpr uris = eqIfNotNull(uri(left), uri(right));
   1.366  		GeneralDBSqlCase scase = new GeneralDBSqlCase();
   1.367  		scase.when(or(isNotNull(bNode(left)), isNotNull(bNode(right))), bnodes);
   1.368  		scase.when(or(isNotNull(uri(left)), isNotNull(uri(right))), uris);
   1.369  		return literalEqual(left, right, scase);
   1.370 -	}
   1.371 +			}
   1.372  
   1.373  	private GeneralDBSqlExpr valueOf(Value value) {
   1.374  		if (value instanceof Literal) {
   1.375 @@ -592,8 +598,8 @@
   1.376  	 */
   1.377  	@Override
   1.378  	public void meet(FunctionCall functionCall)
   1.379 -	throws UnsupportedRdbmsOperatorException
   1.380 -	{
   1.381 +			throws UnsupportedRdbmsOperatorException
   1.382 +			{
   1.383  		Function function = FunctionRegistry.getInstance().get(functionCall.getURI());
   1.384  
   1.385  		if(function instanceof SpatialConstructFunc)
   1.386 @@ -746,7 +752,7 @@
   1.387  			meetNode(functionCall);
   1.388  		}
   1.389  
   1.390 -	}
   1.391 +			}
   1.392  
   1.393  	public GeneralDBSqlExpr spatialFunction(FunctionCall functionCall) throws UnsupportedRdbmsOperatorException
   1.394  	{
   1.395 @@ -1179,7 +1185,7 @@
   1.396  			return geoArea(leftArg);
   1.397  		}
   1.398  		//GeoSPARQL's distance must be added at this place
   1.399 -		
   1.400 +
   1.401  		//Should never reach this place
   1.402  		return null;
   1.403  	}
   1.404 @@ -1209,7 +1215,7 @@
   1.405  		else if(function.getURI().equals(GeoConstants.isSimple))
   1.406  		{
   1.407  			return isSimple(arg);
   1.408 -			
   1.409 +
   1.410  		} else if (function.getURI().equals(GeoConstants.asGML)) {
   1.411  			return asGML(arg);
   1.412  		}
     2.1 --- a/generaldb/src/main/java/org/openrdf/sail/generaldb/evaluation/GeneralDBSqlJoinBuilder.java	Tue Jul 03 19:02:28 2012 +0300
     2.2 +++ b/generaldb/src/main/java/org/openrdf/sail/generaldb/evaluation/GeneralDBSqlJoinBuilder.java	Thu Jul 05 17:05:31 2012 +0300
     2.3 @@ -149,6 +149,15 @@
     2.4  		StringBuilder from = new StringBuilder();
     2.5  		from.append(getTable()).append(" ").append(alias);
     2.6  		for (GeneralDBSqlJoinBuilder join : joins) {
     2.7 +			/**
     2.8 +			 * Reverting datetime_values join to LEFT. 
     2.9 +			 * Had previously made it INNER to change
    2.10 +			 * when it would be executed
    2.11 +			 */
    2.12 +			if(join.getTable().equals("datetime_values"))
    2.13 +			{
    2.14 +				join.setLeft(true);
    2.15 +			}
    2.16  			appendJoin(from, join);
    2.17  		}
    2.18  		for (GeneralDBSqlJoinBuilder left : getLeftJoins()) {
     3.1 --- a/generaldb/src/main/java/org/openrdf/sail/generaldb/optimizers/GeneralDBValueJoinOptimizer.java	Tue Jul 03 19:02:28 2012 +0300
     3.2 +++ b/generaldb/src/main/java/org/openrdf/sail/generaldb/optimizers/GeneralDBValueJoinOptimizer.java	Thu Jul 05 17:05:31 2012 +0300
     3.3 @@ -36,6 +36,8 @@
     3.4  import org.openrdf.sail.generaldb.schema.HashTable;
     3.5  import org.openrdf.sail.generaldb.schema.LiteralTable;
     3.6  import org.openrdf.sail.generaldb.schema.URITable;
     3.7 +import org.slf4j.Logger;
     3.8 +import org.slf4j.LoggerFactory;
     3.9  
    3.10  /**
    3.11   * Adds LEFT JOINs to the query for value tables.
    3.12 @@ -115,29 +117,29 @@
    3.13  
    3.14  	@Override
    3.15  	public void meetFromItem(GeneralDBFromItem node)
    3.16 -	throws RuntimeException
    3.17 -	{
    3.18 +			throws RuntimeException
    3.19 +			{
    3.20  		GeneralDBFromItem top = parent;
    3.21  		parent = join;
    3.22  		join = node;
    3.23  		super.meetFromItem(node);
    3.24  		join = parent;
    3.25  		parent = top;
    3.26 -	}
    3.27 +			}
    3.28  
    3.29  	@Override
    3.30  	public void meet(GeneralDBUnionItem node)
    3.31 -	throws RuntimeException
    3.32 -	{
    3.33 +			throws RuntimeException
    3.34 +			{
    3.35  		stack.add(node);
    3.36  		super.meet(node);
    3.37  		stack.remove(stack.size() - 1);
    3.38 -	}
    3.39 +			}
    3.40  
    3.41  	@Override
    3.42  	public void meet(GeneralDBSelectQuery node)
    3.43 -	throws RuntimeException
    3.44 -	{
    3.45 +			throws RuntimeException
    3.46 +			{
    3.47  		query = node;
    3.48  		parent = node.getFrom();
    3.49  		join = node.getFrom();
    3.50 @@ -145,12 +147,12 @@
    3.51  		join = null;
    3.52  		parent = null;
    3.53  		query = null;
    3.54 -	}
    3.55 +			}
    3.56  
    3.57  	@Override
    3.58  	public void meet(GeneralDBHashColumn node)
    3.59 -	throws RuntimeException
    3.60 -	{
    3.61 +			throws RuntimeException
    3.62 +			{
    3.63  		if (hashes == null || hashes.getName() == null) {
    3.64  			super.meet(node);
    3.65  		}
    3.66 @@ -160,22 +162,22 @@
    3.67  			String tableName = hashes.getName();
    3.68  			join(var, alias, tableName, false);
    3.69  		}
    3.70 -	}
    3.71 +			}
    3.72  
    3.73  	@Override
    3.74  	public void meet(GeneralDBBNodeColumn node)
    3.75 -	throws RuntimeException
    3.76 -	{
    3.77 +			throws RuntimeException
    3.78 +			{
    3.79  		GeneralDBColumnVar var = node.getRdbmsVar();
    3.80  		String alias = "b" + getDBName(var);
    3.81  		String tableName = bnodes.getName();
    3.82  		join(var, alias, tableName);
    3.83 -	}
    3.84 +			}
    3.85  
    3.86  	@Override
    3.87  	public void meet(GeneralDBDatatypeColumn node)
    3.88 -	throws RuntimeException
    3.89 -	{
    3.90 +			throws RuntimeException
    3.91 +			{
    3.92  		GeneralDBColumnVar var = node.getRdbmsVar();
    3.93  		//XXX If spatial, I don't want this action to take place
    3.94  		if(!var.isSpatial())
    3.95 @@ -184,24 +186,35 @@
    3.96  			String tableName = literals.getDatatypeTable().getName();
    3.97  			join(var, alias, tableName);
    3.98  		}
    3.99 -	}
   3.100 +			}
   3.101  
   3.102  	@Override
   3.103  	public void meet(GeneralDBDateTimeColumn node)
   3.104 -	throws RuntimeException
   3.105 -	{
   3.106 +			throws RuntimeException
   3.107 +			{
   3.108  		GeneralDBColumnVar var = node.getRdbmsVar();
   3.109  		String alias = "t" + getDBName(var);
   3.110  		String tableName = literals.getDateTimeTable().getName();
   3.111 -		join(var, alias, tableName);
   3.112 -	}
   3.113 +
   3.114 +		/**
   3.115 +		 * XXX in the default case this should be true!!
   3.116 +		 * Have changed to false to interleave these types of join with
   3.117 +		 * others involving predicate tables (i.e. hasAcquisitionTime)
   3.118 +		 * 
   3.119 +		 * -> By default, left joins are added to query after the inner ones
   3.120 +		 * 
   3.121 +		 * -> Reverting this in GeneralDBSqlJoinBuilder. The join actually 
   3.122 +		 * executed will be LEFT after all
   3.123 +		 */
   3.124 +		join(var, alias, tableName,false);
   3.125 +			}
   3.126  
   3.127  
   3.128  	//Careful! Changes at the alias' name can cause great problems in the query plan!
   3.129  	@Override
   3.130  	public void meet(GeneralDBLabelColumn node)
   3.131 -	throws RuntimeException
   3.132 -	{
   3.133 +			throws RuntimeException
   3.134 +			{
   3.135  		GeneralDBColumnVar var = node.getRdbmsVar();
   3.136  		//
   3.137  		String alias = "l" + getDBName(var);
   3.138 @@ -224,57 +237,57 @@
   3.139  
   3.140  		}
   3.141  
   3.142 -	}
   3.143 +			}
   3.144  
   3.145  	@Override
   3.146  	public void meet(GeneralDBLongLabelColumn node)
   3.147 -	throws RuntimeException
   3.148 -	{
   3.149 +			throws RuntimeException
   3.150 +			{
   3.151  		GeneralDBColumnVar var = node.getRdbmsVar();
   3.152  		String alias = "ll" + getDBName(var);
   3.153  		String tableName = literals.getLongLabelTable().getName();
   3.154  		join(var, alias, tableName);
   3.155 -	}
   3.156 +			}
   3.157  
   3.158  	@Override
   3.159  	public void meet(GeneralDBLanguageColumn node)
   3.160 -	throws RuntimeException
   3.161 -	{
   3.162 +			throws RuntimeException
   3.163 +			{
   3.164  		GeneralDBColumnVar var = node.getRdbmsVar();
   3.165  		String alias = "g" + getDBName(var);
   3.166  		String tableName = literals.getLanguageTable().getName();
   3.167  		join(var, alias, tableName);
   3.168 -	}
   3.169 +			}
   3.170  
   3.171  	@Override
   3.172  	public void meet(GeneralDBNumericColumn node)
   3.173 -	throws RuntimeException
   3.174 -	{
   3.175 +			throws RuntimeException
   3.176 +			{
   3.177  		GeneralDBColumnVar var = node.getRdbmsVar();
   3.178  		String alias = "n" + getDBName(var);
   3.179  		String tableName = literals.getNumericTable().getName();
   3.180  		join(var, alias, tableName);
   3.181 -	}
   3.182 +			}
   3.183  
   3.184  	@Override
   3.185  	public void meet(GeneralDBLongURIColumn node)
   3.186 -	throws RuntimeException
   3.187 -	{
   3.188 +			throws RuntimeException
   3.189 +			{
   3.190  		GeneralDBColumnVar var = node.getRdbmsVar();
   3.191  		String alias = "lu" + getDBName(var);
   3.192  		String tableName = uris.getLongTableName();
   3.193  		join(var, alias, tableName);
   3.194 -	}
   3.195 +			}
   3.196  
   3.197  	@Override
   3.198  	public void meet(GeneralDBURIColumn node)
   3.199 -	throws RuntimeException
   3.200 -	{
   3.201 +			throws RuntimeException
   3.202 +			{
   3.203  		GeneralDBColumnVar var = node.getRdbmsVar();
   3.204  		String alias = "u" + getDBName(var);
   3.205  		String tableName = uris.getShortTableName();
   3.206  		join(var, alias, tableName);
   3.207 -	}
   3.208 +			}
   3.209  
   3.210  	private CharSequence getDBName(GeneralDBColumnVar var) {
   3.211  		String name = var.getName();
   3.212 @@ -290,18 +303,45 @@
   3.213  	private void join(GeneralDBColumnVar var, String alias, String tableName, boolean left) {
   3.214  		if (!isJoined(alias)) {
   3.215  			GeneralDBFromItem valueJoin = valueJoin(alias, tableName, var, left);
   3.216 +
   3.217 +			if(tableName.equals("datetime_values"))//The object I just created involves a datetime value
   3.218 +			{
   3.219 +				int counter = 0;
   3.220 +				//Must now find a connection with previous tables
   3.221 +				for(GeneralDBFromItem tmp : join.getJoins())
   3.222 +				{
   3.223 +					GeneralDBFromItem result = tmp.getFromItem(var.getAlias());
   3.224 +					if (result == null)
   3.225 +						counter++;
   3.226 +					else
   3.227 +					{
   3.228 +						break;
   3.229 +					}
   3.230 +
   3.231 +				}
   3.232 +
   3.233 +				if(counter==join.getJoins().size())
   3.234 +				{
   3.235 +					//If failure to locate an appropriate entry upwards -> revert to default behavior
   3.236 +					Logger logger = LoggerFactory.getLogger(GeneralDBValueJoinOptimizer.class);
   3.237 +					logger.error("[GeneralDBValueJoinOptimizer.info] Failed to push datetime join upwards");
   3.238 +				}
   3.239 +				else
   3.240 +				{
   3.241 +					join.getJoins().add(counter+1,valueJoin);
   3.242 +					return;
   3.243 +				}
   3.244 +			}
   3.245 +
   3.246 +			//DEFAULT BEHAVIOR
   3.247  			if (join == parent || join.getFromItem(var.getAlias()) != null) {
   3.248  				join.addJoin(valueJoin);
   3.249  			}
   3.250  			else {
   3.251  				parent.addJoinBefore(valueJoin, join);
   3.252  			}
   3.253 +
   3.254  		}
   3.255 -//		else
   3.256 -//		{
   3.257 -//			//XXX here for debugging purposes, remove afterwards
   3.258 -//			System.out.println("Quite a common phenomenon");
   3.259 -//		}
   3.260  	}
   3.261  
   3.262  	private boolean isJoined(String alias) {
   3.263 @@ -318,19 +358,19 @@
   3.264  
   3.265  		//FIXME must find I way so that this code runs on the LAST
   3.266  		//occurrence of geo_values!!! => Fill structures used by next optimizer -> SpatialJoinOptimizer
   3.267 -		
   3.268 +
   3.269  		//Commented code because another approach was followed on 09/09/2011. 
   3.270  		//Switched effort to creating a new optimizer dealing with TupleExpressions
   3.271 -//		if(tableName.equals("geo_values"))
   3.272 -//		{
   3.273 -//			geo_values_occurences++;
   3.274 -//			if(!spatiallyEnabled)
   3.275 -//			{
   3.276 -//				exprToAppend.addAll(query.getSpatialFilters());
   3.277 -//				query.getFilters().removeAll(query.getSpatialFilters());
   3.278 -//				spatiallyEnabled = true;
   3.279 -//			}
   3.280 -//		}
   3.281 +		//		if(tableName.equals("geo_values"))
   3.282 +		//		{
   3.283 +		//			geo_values_occurences++;
   3.284 +		//			if(!spatiallyEnabled)
   3.285 +		//			{
   3.286 +		//				exprToAppend.addAll(query.getSpatialFilters());
   3.287 +		//				query.getFilters().removeAll(query.getSpatialFilters());
   3.288 +		//				spatiallyEnabled = true;
   3.289 +		//			}
   3.290 +		//		}
   3.291  
   3.292  		//
   3.293  		return j;