Hi,
Here is a quick and dirty class I wrote yesterday in order to experiment with
the (very useful) table function wrappers provided by Rick.
This function will return the list of all children from a given node (through
the relation Zones.ref <--> Zones.parent).
The table name and the column that serves as reference to the parent node are
all hard coded. But I think you might be found that useful.
Please note that in it current implementation, it could be used both for trees
and graphs containing cycles.
Hope this helps,
Sylvain.
Vrin26 a écrit :
Hi,
Can any one help me with an idea, how I can do a recursion for this issue.
Thanks.
Rick Hillegas-2 wrote:
Vrin26 wrote:
Hi,
I need to do a recursive query on a single derby database table.
In Derby database documents it is mentioned that this derby doesn't
support
recursive queries.
Is there any other work around to handle this scenario?
Thanks
You can push the recursion into a table function or into a database
procedure which returns a result set. The table function documentation
talks about wrapping external data sources, but you can also use table
functions to wrap complicated processing inside Derby itself. See
http://db.apache.org/derby/docs/10.5/devguide/devguide-single.html#cdevspecialtabfuncs
The CREATE PROCEDURE statement is documented here:
http://db.apache.org/derby/docs/10.5/ref/ref-single.html#crefsqlj95081
Hope this helps,
-Rick
--
Website: http://www.chicoree.fr
package fr.chicoree.derby;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Set;
import sun.javadb.vti.core.EnumeratorTableFunction;
/*
Works on this table:
CREATE TABLE Zones (
-- Unique ID
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
-- Reference to the parent
parent INT REFERENCES Zones(id),
-- désignation
designation CHAR(80) NOT NULL
);
Usage:
CREATE FUNCTION AllChildren(rootNode INT) RETURNS TABLE (Children INT)
LANGUAGE java
PARAMETER STYLE DERBY_JDBC_RESULT_SET
READS SQL DATA
EXTERNAL NAME 'fr.chicoree.derby.AllChildren.allChildren'
;
-- Get all children of node 2:
SELECT * FROM TABLE (AllChildren(2) ) AS T;
*/
public class AllChildren extends EnumeratorTableFunction {
static final String[] columns = { "Children" };
public AllChildren(int rootNode) throws SQLException {
super(columns);
Set<Integer> subTree = new HashSet<Integer>();
Set<Integer> parentSet = new HashSet<Integer>();
parentSet.add(rootNode);
Connection conn = DriverManager.getConnection(
"jdbc:default:connection" );
Statement stmt = conn.createStatement();
final String query = "SELECT Children.id " +
" FROM Zones AS
Children " +
" INNER JOIN Zones AS
Parent " +
" ON Parent.id =
Children.parent" +
" WHERE Parent.id in
(%s)";
int subTreeSize = subTree.size();
int subTreePrevSize;
do {
StringBuilder args = new StringBuilder();
String glue = "";
for(Integer node : parentSet) {
args.append(glue);
args.append(node);
glue = ",";
}
// System.err.println(String.format(query,
args.toString()));
ResultSet rs = stmt.executeQuery(String.format(query,
args.toString()));
parentSet = new HashSet<Integer>();
while(rs.next()) {
Integer child = rs.getInt(1);
subTree.add(child);
parentSet.add(child);
}
subTreePrevSize = subTreeSize;
subTreeSize = subTree.size();
} while(subTreePrevSize < subTreeSize);
setEnumeration(subTree);
}
public static ResultSet allChildren(int rootNode) throws SQLException
{ return new
AllChildren(rootNode); }
@Override
public String[] makeRow(Object node) throws SQLException {
return new String[] { node.toString() };
}
}