double ParameterizedFilter::EvaluateConditionNonJoinWeight(Descriptor &d, bool for_or)
{
	// Interpretation of weight:
	// an approximation of logarithm of answer size
	// (in case of for_or: an approximation of (full_table - answer) size)
	// 0 -> time is very short (constant).
	// high weight -> schedule this query to be executed later
	double eval = 0.0;
	_uint64 no_distinct, no_distinct2;
	_uint64 answer_size;

	if(d.IsTrue() || d.IsFalse())
		eval = 0;				// constant time
	else if(d.IsType_AttrValOrAttrValVal()) {		// typical condition: attr=val
		if(!d.encoded) {
			return log(1 + double(d.attr.vc->NoTuples())) + 5;			// +5 as a penalty for complex expression
		}
		SingleColumn* col = static_cast<SingleColumn*>(d.attr.vc);
		answer_size = col->ApproxAnswerSize(d);
		if(for_or)
			answer_size = d.attr.vc->NoTuples() - answer_size;
		_int64 no_in_values = 1;
		if(d.op == O_IN || d.op == O_NOT_IN) {
			MultiValColumn* iscol = static_cast<MultiValColumn*>(d.val1.vc);
			no_in_values = iscol->NoValues(NULL);
		}
		eval = log(1 + double(answer_size));		// approximate size of the result
		if(no_in_values > 1)
			eval += log(double(no_in_values)) * 0.5;	// INs are potentially slower (many comparisons needed)
		if(col->Type().IsString() && !col->Type().IsLookup())
			eval += 0.5;							// strings are slower
		if(col->Type().IsFloat())
			eval += 0.1;							// floats are slower
		if(d.op == O_LIKE || d.op == O_NOT_LIKE)
			eval += 0.2;							// these operators need more work
	} else if(d.IsType_AttrAttr()) {				// attr=attr on the same table
		_uint64 no_obj = d.attr.vc->NoTuples();		// changed to uint64 to prevent negative logarithm for NULL_VALUE_64
		if(!d.encoded)
			return log(1 + double(2 * no_obj)) + 5;		// +5 as a penalty for complex expression
		else if(d.op == O_EQ) {
			no_distinct = d.attr.vc->GetApproxDistVals(false);
			if(no_distinct == 0)
				no_distinct = 1;
			no_distinct2 = d.val1.vc->GetApproxDistVals(false);
			if(no_distinct2 == 0)
				no_distinct2 = 1;
			if(no_distinct2 > no_distinct)
				no_distinct = no_distinct2;					// find the attribute with smaller abstract classes
			if(for_or)
				eval = log(1 + (no_obj - double(no_obj) / no_distinct));
			else
				eval = log(1 + double(no_obj) / no_distinct);	// size of the smaller abstract class
		} else {
			eval = log(1 + double(no_obj) / 2);	// other operators filter potentially a half of objects
		}
		eval += 1;			// add to compensate opening two packs
	} else if(d.IsType_OrTree() && !d.IsType_Join()) {
		eval = d.tree->root->EvaluateConditionWeight(this, for_or);
	} else {	// expressions and other types, incl. joins (to be calculated separately)
		if(d.IsType_IBExpression())
			return log(1 + double(d.attr.vc->NoTuples())) + 2;		// +2 as a penalty for IB complex expression
		eval = 99999;
	}
	return eval;
}