A statement like this

update weblogcategory,weblogcategoryassoc
 set weblogcategory.parentid = weblogcategoryassoc.ancestorid
 where weblogcategory.id = weblogcategoryassoc.categoryid
 and weblogcategoryassoc.relation = 'PARENT';

is not a multi-table update.  It is actually updating only weblogcategory
based on a join.  It's the join syntax in the update that is non-standard. I
think it can be rephrased using a nested select in a way that will work for
our "supported" dbs.

Here's a shot with what I think is standard SQL.
I only tried on mySQL, but I think it should work for Derby and
Oracle.  You will want to test this of course.

update weblogcategory as wc set wc.parentid =
 (select wca.ancestorid from weblogcategoryassoc as wca
         where wc.id = wca.categoryid and wca.relation='PARENT')

Note that wc.id is "bound" at the scope of the row being updated, and I
think this is what you want.

Dave's approach should work too, but it may take a while longer on larger sites. If it's tolerable, we can just go with that; it may not be worth the effort of testing this approach.

--a.


----- Original Message ----- From: "Allen Gilliland" <[EMAIL PROTECTED]>
To: <[email protected]>
Sent: Friday, November 17, 2006 9:14 AM
Subject: Re: svn commit: r475368 [1/2] - in /incubator/roller/trunk:
metadata/database/ metadata/database/hibernate/
src/org/apache/roller/business/ src/org/apache/roller/business/hibernate/
src/org/apache/roller/pojos/ src/org/apache/roller/ui/authoring/stru


sweet, thanks.  i was planning on doing the same thing since unfortunately
there is no sql standard for doing multi-table updates like you said :/

what you have looks fine to me.  we can put the sql in the upgrade guide
if you want, but i think the is more confusing than it's worth.  i would
expect that running the code below is fast enough for most users.  only
people running very large installations would really need to run the
direct sql and i figure that those people probably aren't reading the
upgrade guide anyways.

i am also looking at adding that 'path' column so that we can query for
entries/bookmarks against whole sections of the category/folder trees much
more easily.  there are actually a number of places where i have seen this
would probably make a very nice performance improvement, such in the
BookmarkPlugin which currently walks the entire folder tree to get all
bookmarks on every rendering :/

-- Allen


Dave wrote:
Heads up...

I'm using Derby so I needed to fix the below SQL:

+# this needs to be done in a database independent manner before
releasing
+update weblogcategory,weblogcategoryassoc
+set weblogcategory.parentid = weblogcategoryassoc.ancestorid
+where weblogcategory.id = weblogcategoryassoc.categoryid
+and weblogcategoryassoc.relation = 'PARENT';
+
+# also need to set proper parentid for folders
+update folder,folderassoc
+set folder.parentid = folderassoc.ancestorid
+where folder.id = folderassoc.folderid
+and folderassoc.relation = 'PARENT';

Looks like the only databases that support multi-table updates are
MySQL, MS SQL Server and Oracle -- and they all do it differently. So
I did the work in Java in UpdateDatabase.java and committed what
worked for me. Please review. Here's the important part of the code:

           PreparedStatement selectParents = con.prepareStatement(
               "select categoryid, ancestorid from
weblogcategoryassoc where relation='PARENT'");
           PreparedStatement updateParent = con.prepareStatement(
               "update weblogcategory set parentid=? where id=?");
           ResultSet parentSet = selectParents.executeQuery();
           while (parentSet.next()) {
               String categoryid = parentSet.getString(1);
               String parentid = parentSet.getString(2);
               updateParent.clearParameters();
               updateParent.setString( 1, parentid);
               updateParent.setString( 2, categoryid);
               updateParent.executeUpdate();
           }

           selectParents = con.prepareStatement(
               "select folderid, ancestorid from folderassoc where
relation='PARENT'");
           updateParent = con.prepareStatement(
               "update folder set parentid=? where id=?");
           parentSet = selectParents.executeQuery();
           while (parentSet.next()) {
               String folderid = parentSet.getString(1);
               String parentid = parentSet.getString(2);
               updateParent.clearParameters();
               updateParent.setString( 1, parentid);
               updateParent.setString( 2, folderid);
               updateParent.executeUpdate();
           }

Obviously, it's going to be slower than the MySQL version you created,
so perhaps we need to document the SQL version in the install guide
too.

- Dave


Reply via email to