• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: [ANN] ExistsInRelationshipQualifier: WHERE EXISTS (SELECT 1 FROM A WHERE ...)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [ANN] ExistsInRelationshipQualifier: WHERE EXISTS (SELECT 1 FROM A WHERE ...)


  • Subject: Re: [ANN] ExistsInRelationshipQualifier: WHERE EXISTS (SELECT 1 FROM A WHERE ...)
  • From: Kaj Hejer <email@hidden>
  • Date: Tue, 19 Apr 2005 19:07:04 +0200

Hi!

Thank you again for helping me with this issue!

I think I may have found a possible bug in ExistsInRelationshipQualifier when using it with ec.objectsWithFetchSpecification instead of in-memory filtering. When running in-memory filtering I get the result I expect. When using ec.objectsWithFetchSpecification I don't get the expected results.

I have been looking at the sql and it seems that when generating sql is does not have the correct subquery for the SELECT inside the EXISTS part.

I get the following where part of my sql:

  EXISTS (SELECT 'x' FROM PERSON A0 WHERE A0.PERSONID = 1638))

but the correct one is

EXISTS (SELECT 1 FROM BESVART_SKJEMA A0 WHERE A0.PERSONID = 1638 AND t0.SPORREUNDID = a0.SPORREUNDID)

(t0 is here SPORREUND which is the entity beeing search for)

I make the qualifier by the following code:

args = new NSArray(new Object[] { person.getPersonID() });
EOQualifier sporreundersokelseQual = EOQualifier.qualifierWithQualifierFormat(
"personID = %@", args);
EOQualifier existsQual = new ExistsInRelationshipQualifier("personerBesvart", sporreundersokelseQual);


The search is done against the entity Sporreundersokelse (table is SPORREUND)

The to-many relationships is between the tables Sporreundersokelse and Person where BESVART_SKJEMA is the linkingtable.

On 28. feb. 2005 you sendt me an enhanced version of QualifierGenerationSupport with the dependancy on QualifierUtilities. Can there be something strange is this enhanced version? I copied this file to http://folk.uio.no/kajh/tmp/QualifierGenerationSupport.java

I'm on WO5.2.3.


-Kaj :)






On 19. apr 2005, at 14.30, Kaj Hejer wrote:

Hi!

Nope, I didn't! After added these lines ec.objectsWithFetchSpecification works just fine with ExistsInRelationshipQualifier.

Thank you for helping me with this issue!


-Kaj :)



On 19. apr 2005, at 09.20, <email@hidden> wrote:

Kaj,

did you register the support class like so:

		EOQualifierSQLGeneration.Support.setSupportForClass(
			new ExistsInRelationshipQualifierSupport(),
			ExistsInRelationshipQualifier.class);

The best place to do this would be in a framework's principal class or
your application's main method.

Pierre

-----Original Message-----
From: Kaj Hejer [mailto:email@hidden]
Sent: Monday, April 18, 2005 10:28 PM
To: Pierre Bernard
Cc: email@hidden
Subject: Re: [ANN] ExistsInRelationshipQualifier: WHERE EXISTS (SELECT 1
FROM A WHERE ...)



Hi!

Thank you for ExistsInRelationshipQualifier and the other usefull
qualifiers you have published!

I use the ExistsInRelationshipQualifier in
EOQualifier.filteredArrayWithQualifier and this works just perfect :)

Just now I for the first time tried to use a
ExistsInRelationshipQualifier in a ec.objectsWithFetchSpecification and


now I get:

java.lang.IllegalArgumentException: Qualifier (personerBesvart CONTAINS

((personID = 1638)) (class ExistsInRelationshipQualifier (does not
implement EOQualifierSQLGeneration

Can it be something wrong I do? Any ideas? The same qulifier works just

fine for in-memory filtering.

I'm seeing this with WO5.2.3 on osx 10.3.8 and Oracle 9.2.

The full stacktrace is as follows:

2005-04-18 22:15:21 CEST] <WorkerThread1>
<com.webobjects.appserver._private.WOComponentRequestHandler>:
Exception occurred while handling request:
java.lang.IllegalArgumentException: Qualifier (personerBesvart CONTAINS


((personID = 1638)) (class ExistsInRelationshipQualifier (does not
implement EOQualifierSQLGeneration
[2005-04-18 22:15:21 CEST] <WorkerThread1>
java.lang.IllegalArgumentException: Qualifier (personerBesvart CONTAINS


((personID = 1638)) (class ExistsInRelationshipQualifier (does not
implement EOQualifierSQLGeneration
at
com.webobjects.eoaccess.EOQualifierSQLGeneration$Support._schemaBasedQ ua


lifierWithRootEntity(EOQualifierSQLGeneration.java:163)
at
com.webobjects.eoaccess.EOQualifierSQLGeneration$_NotQualifierSupport. sc


hemaBasedQualifierWithRootEntity(EOQualifierSQLGeneration.java:564)
at
com.webobjects.eoaccess.EOQualifierSQLGeneration$Support._schemaBasedQ ua


lifierWithRootEntity(EOQualifierSQLGeneration.java:165)
at
com.webobjects.eoaccess.EOQualifierSQLGeneration$_OrQualifierSupport.s ch


emaBasedQualifierWithRootEntity(EOQualifierSQLGeneration.java:536)
at
com.webobjects.eoaccess.EOQualifierSQLGeneration$Support._schemaBasedQ ua


lifierWithRootEntity(EOQualifierSQLGeneration.java:165)
at
com.webobjects.eoaccess.EODatabaseChannel.selectObjectsWithFetchSpecif ic


ation(EODatabaseChannel.java:210)
at
com.webobjects.eoaccess.EODatabaseContext._objectsWithFetchSpecificati on


EditingContext(EODatabaseContext.java:3196)
at
com.webobjects.eoaccess.EODatabaseContext.objectsWithFetchSpecificatio n(


EODatabaseContext.java:3337)
at
com.webobjects.eocontrol.EOObjectStoreCoordinator.objectsWithFetchSpec if


ication(EOObjectStoreCoordinator.java:539)
at
com.webobjects.eocontrol.EOEditingContext.objectsWithFetchSpecificatio n(


EOEditingContext.java:4053)
at
com.webobjects.eocontrol.EOEditingContext.objectsWithFetchSpecificatio n(


EOEditingContext.java:4438)


-Kaj :)


On 28. feb 2005, at 09.22, <email@hidden> wrote:

Hi!

An enhanced version of QualifierGenerationSupport with the dependancy

on QualifierUtilities removed looks like below.

Pierre Bernard


package my.access;

import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.util.StringTokenizer;
import java.util.WeakHashMap;

import org.apache.xerces.impl.xpath.regex.Match;
import org.apache.xerces.impl.xpath.regex.RegularExpression;

import com.webobjects.eoaccess.EOAdaptor;
import com.webobjects.eoaccess.EOAttribute;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOJoin;
import com.webobjects.eoaccess.EOQualifierSQLGeneration;
import com.webobjects.eoaccess.EORelationship;
import com.webobjects.eoaccess.EOSQLExpression;

import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSForwardException;
import com.webobjects.foundation.NSKeyValueCodingAdditions;
import com.webobjects.foundation.NSMutableDictionary;

import my.control.Qualifier;

/** Support methods for SQL generation
 *
 * @author bernard
 */
public abstract class QualifierGenerationSupport extends
EOQualifierSQLGeneration.Support
{
	// Protected class variables

	protected static WeakHashMap prefixesByExpression;
	protected static String[] prefixes;
	protected static WeakReference[] locks;

	// Static initializer

	static {
		char start = 'A', end = 'Z';
		int count = end - start;
		int offset = 0;

		QualifierGenerationSupport.prefixes = new String[count];

		for (int i = 0; i < count; i++)
		{
			char prefix = (char) (start + i);

			if (prefix == 'T')
			{
				offset += 1;
			}
			else
			{
				QualifierGenerationSupport.prefixes[i] =
new
Character(prefix).toString();
			}
		}

QualifierGenerationSupport.locks = new
WeakReference[count - offset];
		QualifierGenerationSupport.prefixesByExpression = new
WeakHashMap(count - offset);
	}

	// Protected instance methods

	protected EOAttribute attributeForPath(EOEntity entity, String
keyPath)
	{
		if (keyPath != null)
		{
			StringTokenizer tokenizer =
				new StringTokenizer(keyPath,
NSKeyValueCodingAdditions.KeyPathSeparator);
			EORelationship relationship = null;

			while (tokenizer.hasMoreElements())
			{
				String key = tokenizer.nextToken();

				if (tokenizer.hasMoreElements())
				{
					relationship =
entity.anyRelationshipNamed(key);
				}
				else
				{
					return
entity.anyAttributeNamed(key);
				}

				if (relationship != null)
				{
					entity =
relationship.destinationEntity();
				}
				else
				{
					return null;
				}
			}

			return null;
		}

		return null;
	}

protected EORelationship relationshipForPath(EOEntity entity,
String
keyPath)
	{
		if (keyPath != null)
		{
			StringTokenizer tokenizer =
				new StringTokenizer(keyPath,
NSKeyValueCodingAdditions.KeyPathSeparator);
			EORelationship relationship = null;

			while (tokenizer.hasMoreElements())
			{
				String key = tokenizer.nextToken();

relationship =
entity.anyRelationshipNamed(key);

if (relationship != null) { entity =
relationship.destinationEntity();
				}
				else
				{
					return null;
				}
			}

			return relationship;
		}

		return null;
	}

	protected String optimizeQualifierKeyPath(
		EOEntity entity,
		String keyPath,
		String attributeName)
	{
		if ((keyPath == null) || (keyPath.length() == 0))
		{
			return attributeName;
		}
		else
		{
			EORelationship relationship =
				(entity == null) ? null :
relationshipForPath(entity, keyPath);

if (relationship != null) { NSArray joins = relationship.joins(); int joinCount = (joins == null) ? 0 :
joins.count();

for (int i = joinCount - 1; i >= 0; i--) { EOJoin join = (EOJoin)
joins.objectAtIndex(i);

if
(join.destinationAttribute().name().equals(attributeName))
					{
						String newPath =
Qualifier.allButLastPathComponent(keyPath);
String newAttributeName
= join.sourceAttribute().name();

return
optimizeQualifierKeyPath(entity, newPath,
newAttributeName);
					}
				}
			}

return (keyPath + Qualifier.KEY_PATH_SEPARATOR +
attributeName);
		}
	}

	protected String translateKeyAcrossRelationshipPath(
		String keyPath,
		String relationshipPath,
		EOEntity entity)
	{
		String flattenedKeyPath =
flattenRelationshipPath(keyPath, entity);
		String flattenedRelationshipPath =
flattenRelationshipPath(relationshipPath, entity);
		String translationPath = flattenedRelationshipPath +
Qualifier.KEY_PATH_SEPARATOR;

		if (flattenedKeyPath.startsWith(translationPath))
		{
			String translatedKeyPath =
flattenedKeyPath.substring(translationPath.length());
			EOEntity destinationEntity =
				relationshipForPath(entity,
flattenedRelationshipPath).destinationEntity();

			return optimizeQualifierKeyPath(
				destinationEntity,

Qualifier.allButLastPathComponent(translatedKeyPath),

Qualifier.lastPathComponent(translatedKeyPath));
		}
		else
		{
			StringTokenizer tokenizer =
				new
StringTokenizer(flattenedRelationshipPath,
Qualifier.KEY_PATH_SEPARATOR);
			EOEntity tmpEntity = entity;
			StringBuffer invertedRelationshipPath = new
StringBuffer(flattenedKeyPath.length());

			while (tokenizer.hasMoreElements())
			{
				String relationshipName =
tokenizer.nextToken();
				EORelationship relationship =
tmpEntity.anyRelationshipNamed(relationshipName);

				try
				{
					if
(invertedRelationshipPath.length() > 0)
					{

invertedRelationshipPath.insert(0,
Qualifier.KEY_PATH_SEPARATOR_CHAR);
					}

					invertedRelationshipPath.insert(
						0,

relationship.anyInverseRelationship().name());
				}
				catch (Exception exception)
				{
					throw new
NSForwardException(exception);
				}

tmpEntity =
relationship.destinationEntity();
			}

if
(flattenedKeyPath.indexOf(Qualifier.KEY_PATH_SEPARATOR_CHAR) >=
0)
			{

invertedRelationshipPath.append(Qualifier.KEY_PATH_SEPARATOR_CHAR);
				invertedRelationshipPath.append(

Qualifier.allButLastPathComponent(flattenedKeyPath));
			}

			return optimizeQualifierKeyPath(
				tmpEntity,
				invertedRelationshipPath.toString(),

Qualifier.lastPathComponent(flattenedKeyPath));
		}
	}

protected String flattenRelationshipPath(String path, EOEntity
entity)
	{
		if (path.indexOf(Qualifier.KEY_PATH_SEPARATOR_CHAR) >=
0)
		{
			String relationshipPath = null;
			StringTokenizer tokenizer = new
StringTokenizer(path,
Qualifier.KEY_PATH_SEPARATOR);

			while (tokenizer.hasMoreElements())
			{
				String relationshipName =
tokenizer.nextToken();
				EORelationship relationship =
entity.anyRelationshipNamed(relationshipName);

				if (relationship == null)
				{
					if
(!tokenizer.hasMoreElements())
					{
						return relationshipPath
+ Qualifier.KEY_PATH_SEPARATOR +
relationshipName;
					}
					else
					{
						throw new
IllegalArgumentException(
"No relationship
'"
+
relationshipName
+ "' was
found in entity '"
+
entity.name()
+ "'
while evaluating relationship path '"
								+ path);
					}
				}
				else
				{
					String element;

					if (relationship.isFlattened())
					{
						element =
relationship.relationshipPath();
					}
					else
					{
						element =
relationship.name();
					}

					if (relationshipPath != null)
					{
						relationshipPath =
							relationshipPath
+ Qualifier.KEY_PATH_SEPARATOR + element;
					}
					else
					{
						relationshipPath =
element;
					}

entity =
relationship.destinationEntity();
				}
			}

			return relationshipPath;
		}
		else
		{
			EORelationship relationship =
entity.anyRelationshipNamed(path);

if (relationship == null) { return path; } else { if (relationship.isFlattened()) { return
relationship.relationshipPath();
				}
				else
				{
					return relationship.name();
				}
			}
		}
	}

protected NSMutableDictionary
replaceTableAliasesInExpressionBuffer(
		StringBuffer buffer,
		EOSQLExpression expression)
	{
		NSMutableDictionary aliasesByRelationshipPath =
expression.aliasesByRelationshipPath();
		NSArray subExpressionAliases =
aliasesByRelationshipPath.allKeys();
		int aliasCount = subExpressionAliases.count();

		for (int i = 0; i < aliasCount; i++)
		{
			String relationshipPath = (String)
subExpressionAliases.objectAtIndex(i);
			String alias = (String)
aliasesByRelationshipPath.objectForKey(relationshipPath);
			String newAlias =
aliasPrefixForExpression(expression) + i;
RegularExpression regExp = new
RegularExpression("[ ,(]" + alias +
"[ ,\\,,.]");
			int start = 0;
			Match match = new Match();
			String currentString;

			while (regExp
				.matches(currentString =
buffer.toString(), start,
currentString.length(), match))
			{
				start = match.getBeginning(0) + 1;
				buffer.replace(start, match.getEnd(0) -
1, newAlias);
			}


aliasesByRelationshipPath.setObjectForKey(newAlias,
relationshipPath);
		}

		return aliasesByRelationshipPath;
	}

	protected EOSQLExpression expressionForEntity(EOEntity entity)
	{
		try
		{
			Class expressionClass =
				((EOAdaptor)
EOAdaptor.adaptorWithModel(entity.model())).expressionClass();
			Constructor constructor =
				expressionClass.getConstructor(new
Class[] { EOEntity.class });
			EOSQLExpression expression =
				(EOSQLExpression)
constructor.newInstance(new Object[] { entity });

return expression; } catch (Exception exception) { throw new NSForwardException(exception); } }

	// Protected class methods

	protected static synchronized String
aliasPrefixForExpression(EOSQLExpression expression)
	{
		String prefix = (String)
QualifierGenerationSupport.prefixesByExpression.get(expression);

		if (prefix == null)
		{
			prefix = assignPrefixToExpression(expression);

			if (prefix == null)
			{
				System.gc();

prefix =
assignPrefixToExpression(expression);
			}

			if (prefix == null)
			{
				throw new RuntimeException(
					"The number of available alias
prefixes was exceeded. "
+ "Fix me if you
please");
			}
		}

		return prefix;
	}

	// Private class methods

	private static synchronized String
assignPrefixToExpression(EOSQLExpression expression)
	{
		int count = QualifierGenerationSupport.locks.length;
		int availableIndex = 0;

		while (availableIndex < count)
		{
			WeakReference lock =
QualifierGenerationSupport.locks[availableIndex];

			if ((lock == null) || (lock.get() == null))
			{

QualifierGenerationSupport.locks[availableIndex] = null;

break; } else { availableIndex++; } }

		if (availableIndex < count)
		{
			String prefix =
QualifierGenerationSupport.prefixes[availableIndex];

QualifierGenerationSupport.locks[availableIndex]
= new
WeakReference(expression);

QualifierGenerationSupport.prefixesByExpression.put(expression,
prefix);

			return prefix;
		}
		else
		{
			return null;
		}
	}
}

-----Original Message-----
From: Kaj Hejer [mailto:email@hidden]
Sent: Friday, February 25, 2005 1:33 PM
To: Pierre Bernard
Cc: email@hidden
Subject: Re: [ANN] ExistsInRelationshipQualifier: WHERE EXISTS (SELECT

1
FROM A WHERE ...)



On 17. jan 2005, at 10.22, <email@hidden> wrote:

Hi!

I have added a new code snipped to my web page.

ExistsInRelationshipQualifier: Qualifier to check for the presence of
objects
matching a given qualifier in a to-many relationship. May be combined
with an
EONotQualifier to insure the absence of matching objects.


It is available for download on my web page:
http://homepage.mac.com/i_love_my

P.S.: This code relies on the "Support methods for custom qualifiers"
code snippet which is also available from my web page.




Hi!

Thank you for this and the other codesnippets you have on your
webpage!

I have downloaded
<url:http://homepage.mac.com/i_love_my/inSubQueryQualifier.tar.gz> and
<url:http://homepage.mac.com/i_love_my/customQualifiers.tar.gz> but
still QualifierGenerationSupport is complaining it can't find
QualifierUtilities in the following code:


	protected EOAttribute attributeForPath(EOEntity entity, String
keyPath)
	{
		return QualifierUtilities.attributeForPath(entity,
keyPath);
	}

protected EORelationship relationshipForPath(EOEntity entity,
String
keyPath)
	{
		return QualifierUtilities.relationshipForPath(entity,
keyPath);
	}

Any hints? :)

TIA!


-Kaj :)





********************************************************************* *
This email and any files transmitted with it are intended solely for
the use of the individual or entity to whom they are addressed.
If you have received this email in error please notify the sender
of this message. (email@hidden)
This email message has been checked for the presence of computer
viruses; however this protection does not ensure this message is
virus free.
Banque centrale du Luxembourg; Tel ++352-4774-1; http://www.bcl.lu
********************************************************************* *





********************************************************************** This email and any files transmitted with it are intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the sender of this message. (email@hidden) This email message has been checked for the presence of computer viruses; however this protection does not ensure this message is virus free. Banque centrale du Luxembourg; Tel ++352-4774-1; http://www.bcl.lu **********************************************************************

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
email@hidden


This email sent to email@hidden

Attachment: PGP.sig
Description: This is a digitally signed message part

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

References: 
 >RE: [ANN] ExistsInRelationshipQualifier: WHERE EXISTS (SELECT 1 FROM A WHERE ...) (From: <email@hidden>)
 >Re: [ANN] ExistsInRelationshipQualifier: WHERE EXISTS (SELECT 1 FROM A WHERE ...) (From: Kaj Hejer <email@hidden>)

  • Prev by Date: Re: Bi-directional One-to-one relationship
  • Next by Date: Re: Security and takeValuesFromRequest()
  • Previous by thread: Re: [ANN] ExistsInRelationshipQualifier: WHERE EXISTS (SELECT 1 FROM A WHERE ...)
  • Next by thread: Trigger saveData on session termination
  • Index(es):
    • Date
    • Thread