On Thursday 17 May 2001 09:24, you wrote:
> On Wednesday, May 16, 2001, at 11:46 PM, Fedor Karpelevitch wrote:
> > On Wednesday 16 May 2001 16:45, you wrote:
> >> Eric Dobbs <[EMAIL PROTECTED]> writes:
> >>> Select, Update and Delete all have a where clause in common, but
> >>> Insert and Update both have a need to set columns to values, so
> >>> I think they belong together too. Particularly because I think
> >>> there is a need to support "INSERT OR UPDATE ...".
> >>>
> >>> So maybe we need to create two interfaces here -- one that defines
> >>> methods related to the where clause, and one that defines methods
> >>> related to assigning values to columns.
> >>
> >> Yes, using two interfaces is definitely the Right Thing.
> >
> > I agree here, but my concern is that if you get into multiple
> > inheritance
> > thing you can no longer inherit implementation... Something to think
> > about
> > here....
>
> Yep, inheriting implementation would be nice. So I put all the
> functionality for SELECT, INSERT, UPDATE and DELETE together in my
> first suggestion. When I was extending that to create Select,
> Insert, Update, and Delete objects, my first draft was to make
> Query an abstract class and make the others subclasses. Where
> there were methods in Query that were inappropriate for Insert, I
> would override the inappropriate methods and maybe throw an
> exception. The whole point was to be able to inherit
> implementation while providing an API that reads well. This
> inheritance convenience comes at the expense of having objects
> totally specialized to their task.
hm,hmm.... I do not like providing an API and not implementing it.... It's
just not right... I am not sure how it can be done better.... I don't have a
solid opinion here yet.
>
> >>> Select, and Delete would implement only the "where" interface.
> >>> Update would implement both "where" and "set column" interfaces.
> >>> Insert would implement only the "set column" interface. I don't
> >>> know how to name those interfaces.
> >
> > sounds good, but see above...
> >
> >> So we need a Clause interface and a ColumnMap interface (interface
> >> names negotiable, just tossing out suggestions).
> >
> > I am not sure what Clause interface would mean. I do not see what
> > different
> > clauses have in common....
> > And I am not sure what you mean by ColumnMap interface, is that Eric's
> > "set
> > column"?
>
> I take Dan's suggestion to be names for the two interfaces I suggested.
> I think Where interface would be more specific,
I am still in doubt what Clase (Where) interface function would be...
> and maybe ColumnValueMap.
maybe
>
> >>>> BTW both Statement & Condition implement SQLCode interface which only
> >>>> contains toSQL metod.
> >>
> >> I really don't like the toSQL() method for a class which implements a
> >> SQLCode interface. I would prefer that the standard toString() method
> >> be part of the SQLCode interface, and that toString() be used in place
> >> of toSQL(). Yes, the returned value *is* plenty readable.
> >
> > the reason for toSQL is not readablity (I withdrew that one), but these
> > two
> > things:
> >
> > 1) if you use toString() you end up with LOTS of String concatenation.
> > toSQL
> > returns StringStackBuffer instead. look at the code.
> > 2) toSQL takes DB as parameter ( sig is toSQL(DBdb)) so it has the
> > ability to
> > produce DB-specific SQL if needed.
>
> I like both of those reasons. I like being able to pass in a DB object.
> I'm not sure StringStackBuffer is the right choice for the return type.
I think it is :-) It saves a lot of string concatenation. StringBuffer would
not help much in this case.... In fact current Criteria & friends use
StringStackBuffer and I found that reasonable.
> With a StringStackBuffer you can do .toString("/"). That's reasonable to
> do with a StringStackBuffer, but not reasonable for the SQL we want out.
In our case we'd use .toString() as there is no need for a separator.
> I think I would prefer a StringBuffer. In which case I'd prefer a method
> named toStringBuffer(DB db).
I think using StringBuffer would be less efficient than StringStackBuffer as
you would still have to coipy a lot of strings back and forth. I would name
the method toStringStackBuffer if it was not that long and scary...
>
> >>>> i think adding .and() and .or() methods as described above will make
> >>>> you happy?
> >>>
> >>> Not yet. I think what is bothering me about this model
> >>> is the use of objects to represent the comparisons. I
> >>> don't think an equals operator should be represented as
> >>> an object unto itself. Same for the rest of the logical
> >>> comparison operators.
> >>
> >> I frown on the extra objects that will be instantiated unnecessarily,
> >
> > I do not think I instantiate anything _extra_ here versus method-based
> > approach, because in that case you still need to put _some_ object into
> > your
> > list of conditions, be that Criterion or eanything else. So I think it
> > is
> > just as bad/good. I do not see any problem with that - objects are
> > pretty
> > light.
>
> Every place in the API you propose that has new XYZ() is instantiating
> an object. By contrast, this latest suggestion I've offered...
>
> > new Comparison().equals(col,val).or().equals(col2,val2)
but how do you implement .equals() method? You will have to instanciate
_some_ object to add to your list of conditions, won't you? That's what I
meant... So there should be just as much object instantiation... am I wrong?
>
> ...the Comparison object is instantiated only once. All of the methods
> would modify that Comparison instance and return a reference to it.
> The only place where another instance would be created is when nested
> groups are needed in the comparison. That might look like this:
> new Comparison().equals(col,val).and(
> new Comparison().equals(col2,val2).or().equals(col2,val3))
> which would create SQL like this:
> COL=VAL AND (COL2=VAL2 OR COL2=VAL3)
>
> With your model the equivalent SQL would need something like this:
> new And(new Equals(col,val),
> new Or(new Equals(col2,val2), new Equals(col2,val3)))
so the only difference is _where_ in the code object is created, but the
number should be the same....
On a side note, .equals is a bad name for the method as it looks like an
overload for Object.equals(Object) method, but it has a completely different
semantics which is confusing and is not good.
>
> Two instances in the former, four instances in the latter. Instantiating
> objects is not light, otherwise there wouldn't be any need for the cool
> caching service. I think the methods approach would offer better
> performance and I still think it reads better.
see above....
>
> >> though the interfaces do make for nice Java code. However, this is
> >> code that will be called over and over again, so performance is an
> >> issue.
> >
> > btw in my opinion the better design allows for cleaner reuse of
> > Query/Condition objects (they are thread-safe too) so you will be able
> > to
> > save a lot of the calls etc...
> >
> >>> I'm thinking of another alternative that would use
> >>> methods instead of objects. Like these: .equals(col,val),
> >>> .greaterThan(col,val), .in(col,val[]), .notIn(col,val[])
> >>
> >> I am not adverse to this idea. It will certainly perform much better
> >> than possibly excessive object instantiation.
> >
> > again, i am afraid you'll have to create just as many objects. This
> > approach,
> > however is less flexible. The main reason I made everything an object
> > implementing Condition is that And and Or accepts conditions as members
> > which
> > in turn may be And's and Or's thjis way allowing clean way to create
> > conditions of any complexity. Also code duplication is virtual zero.
WBR, Fedor
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]