Return-Path: Delivered-To: apmail-db-derby-user-archive@www.apache.org Received: (qmail 67256 invoked from network); 1 Mar 2010 19:00:54 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 1 Mar 2010 19:00:54 -0000 Received: (qmail 55368 invoked by uid 500); 1 Mar 2010 19:00:52 -0000 Delivered-To: apmail-db-derby-user-archive@db.apache.org Received: (qmail 55305 invoked by uid 500); 1 Mar 2010 19:00:52 -0000 Mailing-List: contact derby-user-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: List-Id: Reply-To: "Derby Discussion" Delivered-To: mailing list derby-user@db.apache.org Received: (qmail 55298 invoked by uid 99); 1 Mar 2010 19:00:52 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 Mar 2010 19:00:52 +0000 X-ASF-Spam-Status: No, hits=-4.0 required=10.0 tests=RCVD_IN_DNSWL_MED,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: local policy) Received: from [192.18.43.133] (HELO sca-es-mail-2.sun.com) (192.18.43.133) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 Mar 2010 19:00:41 +0000 Received: from fe-sfbay-10.sun.com ([192.18.43.129]) by sca-es-mail-2.sun.com (8.13.7+Sun/8.12.9) with ESMTP id o21J0Jkc029776 for ; Mon, 1 Mar 2010 11:00:20 -0800 (PST) MIME-version: 1.0 Content-transfer-encoding: 7BIT Content-type: text/plain; CHARSET=US-ASCII; format=flowed Received: from conversion-daemon.fe-sfbay-10.sun.com by fe-sfbay-10.sun.com (Sun Java(tm) System Messaging Server 7u2-7.04 64bit (built Jul 2 2009)) id <0KYM00D009XXIG00@fe-sfbay-10.sun.com> for derby-user@db.apache.org; Mon, 01 Mar 2010 11:00:19 -0800 (PST) Received: from richard-hillegas-computer.local ([unknown] [129.150.225.155]) by fe-sfbay-10.sun.com (Sun Java(tm) System Messaging Server 7u2-7.04 64bit (built Jul 2 2009)) with ESMTPSA id <0KYM00IDQA46J560@fe-sfbay-10.sun.com> for derby-user@db.apache.org; Mon, 01 Mar 2010 11:00:06 -0800 (PST) Date: Mon, 01 Mar 2010 11:00:05 -0800 From: Rick Hillegas Subject: Re: how to raise/throw an exception In-reply-to: <1f5d398f1003010838r36437fd3y3fef63392312651a@mail.gmail.com> Sender: Richard.Hillegas@Sun.COM To: Derby Discussion Message-id: <4B8C0EB5.2070200@sun.com> References: <1f5d398f1002260521m2f61f0feyb41c2bf440adb746@mail.gmail.com> <4B87CF9B.6020601@sun.com> <1f5d398f1002260559s753439cdge6c2716f74101ea6@mail.gmail.com> <4B87DCC2.4040608@sun.com> <1f5d398f1002260642q9b6b2e0vda66bd31e73bdbff@mail.gmail.com> <4B87E407.6040908@sun.com> <1f5d398f1002260906q6ceb1536y25d5dff0701b4018@mail.gmail.com> <4B8803D8.9070904@sun.com> <1f5d398f1002261050r209fddc5sca7785f4abdec2e2@mail.gmail.com> <4B881EE6.6090806@sun.com> <1f5d398f1003010838r36437fd3y3fef63392312651a@mail.gmail.com> User-Agent: Thunderbird 2.0.0.23 (Macintosh/20090812) X-Virus-Checked: Checked by ClamAV on apache.org Hi Gabriele, The file in question is derby.log, which I believe you have located. If you are not seeing the information you need there, it may be because you have not set the correct tracepoints in order to force the logging of that information. You may get a broader response to your question if you start a new thread under the title "Debugging lock timeouts". Hope this helps, -Rick Gabriele Kahlout wrote: > So can someone explain me (or refer to where it is explained) how to > read/find this log file with the wanted info? > > 2010/2/26, Rick Hillegas : > >> Hi Gabriele, >> >> The following link will help you debug your lock contention problem: >> http://db.apache.org/derby/faq.html#debug_lock_timeout >> >> Hope this is useful, >> -Rick >> >> Gabriele Kahlout wrote: >> >>> Because of the trigger + procedure the update statement on the >>> affected table throws (not otherwise): >>> >>> java.sql.SQLException: The exception 'java.sql.SQLException: A lock >>> could not be obtained within the time requested' was thrown while >>> evaluating an expression. >>> >>> I tried to make it sleep for 250 nanos. But no avail. >>> >>> 2010/2/26, Rick Hillegas : >>> >>> >>>> Hi Gabriele, >>>> >>>> Some comments inline... >>>> >>>> Gabriele Kahlout wrote: >>>> >>>> >>>>> Perhaps last question: how to pass as parameter also the table? >>>>> >>>>> >>>>> >>>> Here's a revised version of the procedure which takes the table and >>>> column names as parameters: >>>> >>>> public static void vetRow( String tableName, String columnName, int >>>> columnValue ) throws SQLException >>>> { >>>> Connection conn = DriverManager.getConnection( >>>> "jdbc:default:connection" ); >>>> String query = "select count(*) from " + tableName +" where " + >>>> columnName + " = ?"; >>>> System.out.println( query ); >>>> PreparedStatement ps = conn.prepareStatement( query ); >>>> ps.setInt( 1, columnValue ); >>>> ResultSet rs = ps.executeQuery(); >>>> rs.next(); >>>> int result = rs.getInt( 1 ); >>>> >>>> rs.close(); >>>> ps.close(); >>>> >>>> if ( result >= 4 ) { throw new SQLException( "Too many copies of >>>> some value." ); } >>>> } >>>> } >>>> >>>> and the corresponding script to exercise this procedure: >>>> >>>> connect 'jdbc:derby:memory:dummy;create=true'; >>>> >>>> create table t( a int ); >>>> >>>> create procedure vetRow( in tableName varchar( 128 ), in columnName >>>> varchar( 128 ), in arg int ) >>>> language java parameter style java reads sql data >>>> external name 'z.vetRow'; >>>> >>>> create trigger t_trig >>>> no cascade before insert on t >>>> referencing new as newRow >>>> for each row call vetRow( 'T', 'A', newRow.a ); >>>> >>>> insert into t( a ) values ( 1 ); >>>> insert into t( a ) values ( 1 ); >>>> insert into t( a ) values ( 1 ); >>>> insert into t( a ) values ( 1 ); >>>> >>>> -- fails >>>> insert into t( a ) values ( 1 ); >>>> >>>> >>>> >>>>> Also, where can I look to understand why int a would be translated as >>>>> the column a? >>>>> This doesn't help: >>>>> http://developers.sun.com/docs/javadb/10.5.3.0/ref/index.html >>>>> >>>>> >>>>> >>>> You will want to read the syntax descriptions for the CREATE PROCEDURE >>>> and CREATE TRIGGER commands in that Reference Guide. >>>> >>>> Hope this helps, >>>> -Rick >>>> >>>> >>>> >>>> >>>>> 2010/2/26, Rick Hillegas : >>>>> >>>>> >>>>> >>>>>> Hi Gabriele, >>>>>> >>>>>> Here is a vetting procedure which the trigger could call: >>>>>> >>>>>> public static void vetRow( int a ) throws SQLException >>>>>> { >>>>>> Connection conn = DriverManager.getConnection( >>>>>> "jdbc:default:connection" ); >>>>>> PreparedStatement ps = conn.prepareStatement( "select count(*) >>>>>> from t where a = ?" ); >>>>>> ps.setInt( 1, a ); >>>>>> ResultSet rs = ps.executeQuery(); >>>>>> rs.next(); >>>>>> int result = rs.getInt( 1 ); >>>>>> >>>>>> rs.close(); >>>>>> ps.close(); >>>>>> >>>>>> if ( result >= 4 ) { throw new SQLException( "Too many copies >>>>>> of >>>>>> value " + a + " in t." ); } >>>>>> } >>>>>> >>>>>> And here again is the sql script which exercises the trigger. I had to >>>>>> modify the trigger declaration slightly: instead of saying that it >>>>>> "contains sql" this version says "reads sql data": >>>>>> >>>>>> connect 'jdbc:derby:memory:dummy;create=true'; >>>>>> >>>>>> create table t( a int ); >>>>>> >>>>>> create procedure vetRow( in arg int ) >>>>>> language java parameter style java reads sql data >>>>>> external name 'z.vetRow'; >>>>>> >>>>>> create trigger t_trig >>>>>> no cascade before insert on t >>>>>> referencing new as newRow >>>>>> for each row call vetRow( newRow.a ); >>>>>> >>>>>> insert into t( a ) values ( 1 ); >>>>>> insert into t( a ) values ( 1 ); >>>>>> insert into t( a ) values ( 1 ); >>>>>> insert into t( a ) values ( 1 ); >>>>>> >>>>>> -- fails >>>>>> insert into t( a ) values ( 1 ); >>>>>> >>>>>> Depending on your usage pattern, it might make more sense to declare an >>>>>> AFTER trigger which invokes a vetting procedure once per INSERT/UPDATE >>>>>> rather than per row. >>>>>> >>>>>> Hope this helps, >>>>>> -Rick >>>>>> >>>>>> Gabriele Kahlout wrote: >>>>>> >>>>>> >>>>>> >>>>>>> The procedure would run the sanity check query and raise an exception >>>>>>> if the sanity check failed. >>>>>>> Can you show me an example of how this exception could be thrown? >>>>>>> >>>>>>> About the user-coded function, how may I code what I asked for? A loop >>>>>>> that counts for each distinct value it's occurences, and returns >>>>>>> true/false if some count is greater than 5. >>>>>>> >>>>>>> 2010/2/26, Rick Hillegas : >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>>> Hi Gabriele, >>>>>>>> >>>>>>>> Here's an example of how Derby triggers invoke database procedures. >>>>>>>> If >>>>>>>> this is still not clear, please keep asking questions. We will get to >>>>>>>> the bottom of this: >>>>>>>> >>>>>>>> connect 'jdbc:derby:memory:dummy;create=true'; >>>>>>>> >>>>>>>> create table t( a int ); >>>>>>>> >>>>>>>> create procedure vetRow( in arg int ) >>>>>>>> language java parameter style java contains sql >>>>>>>> external name 'z.vetRow'; >>>>>>>> >>>>>>>> create trigger t_trig >>>>>>>> no cascade before insert on t >>>>>>>> referencing new as newRow >>>>>>>> for each row call vetRow( newRow.a ); >>>>>>>> >>>>>>>> insert into t( a ) values ( 1 ); >>>>>>>> >>>>>>>> Another comment inline... >>>>>>>> >>>>>>>> Gabriele Kahlout wrote: >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>>> That's what i do in SQLite. The question is how to do it in java DB >>>>>>>>> sql >>>>>>>>> syntax. >>>>>>>>> In sqlite it is SELECT( RAISE, 'error) WHERE ... >>>>>>>>> in java db?? >>>>>>>>> >>>>>>>>> Also, I was wondering if I could find a way to implement the >>>>>>>>> constraint as a column constraint. Unfortunately the details , are >>>>>>>>> far >>>>>>>>> from complete. >>>>>>>>> http://developers.sun.com/docs/javadb/10.5.3.0/ref/index.html >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>> I don't think so. The only kind of constraint you could use here >>>>>>>> would >>>>>>>> be a CHECK constraint which invokes a user-coded function. The >>>>>>>> function >>>>>>>> would not be allowed to issue SQL. >>>>>>>> >>>>>>>> Hope this helps, >>>>>>>> -Rick >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>>> Basically I'm trying to check that no more than 4 rows have the same >>>>>>>>> value for the column. In SQL that would be the count -group by >>>>>>>>> query, >>>>>>>>> as mentioned below, but since that counts as a not allowed subquery, >>>>>>>>> is there some other way in java db to achieve exactly that? >>>>>>>>> >>>>>>>>> 2010/2/26, Rick Hillegas : >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>>> Hi Gabriele, >>>>>>>>>> >>>>>>>>>> One way to solve this problem would be to have your trigger call a >>>>>>>>>> database procedure, passing in whatever parameters you need from >>>>>>>>>> the >>>>>>>>>> triggering row. The procedure would run the sanity check query and >>>>>>>>>> raise >>>>>>>>>> an exception if the sanity check failed. >>>>>>>>>> >>>>>>>>>> Hope this helps, >>>>>>>>>> -Rick >>>>>>>>>> >>>>>>>>>> Gabriele Kahlout wrote: >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> Hello, >>>>>>>>>>> >>>>>>>>>>> I'm porting my application from SQLite to Java DB, but don't know >>>>>>>>>>> how >>>>>>>>>>> to enforce an assertion, achieved in SQLite by: >>>>>>>>>>> >>>>>>>>>>> st.execute("CREATE TRIGGER _fk_meanings_update_1 BEFORE UPDATE ON >>>>>>>>>>> " >>>>>>>>>>> + >>>>>>>>>>> batTable.getName() + " FOR EACH ROW BEGIN SELECT RAISE(FAIL, >>>>>>>>>>> 'error') >>>>>>>>>>> WHERE (EXISTS (SELECT COUNT(*) FROM " + batTable.getName() + " >>>>>>>>>>> GROUP >>>>>>>>>>> BY " + lastPubColumn.getName() + " HAVING COUNT(*)>"+maxPub+")); >>>>>>>>>>> END;"); >>>>>>>>>>> >>>>>>>>>>> However the constraint couldn't be added as a table constraint, >>>>>>>>>>> and >>>>>>>>>>> I'm not finding how to raise an exception with Java DB, although >>>>>>>>>>> it's >>>>>>>>>>> described here: >>>>>>>>>>> >>>>>>>>>>> http://developers.sun.com/docs/javadb/10.5.3.0/devguide/index.html >>>>>>>>>>> >>>>>>>>>>> One way was to set the identity column to null, but that was not >>>>>>>>>>> allowed at compile time too. I guess I'd have to use some dirty >>>>>>>>>>> way. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>> >>> >>> >> > > >