aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-146/luca-ferrari/postgresql/ch-2.sql145
1 files changed, 145 insertions, 0 deletions
diff --git a/challenge-146/luca-ferrari/postgresql/ch-2.sql b/challenge-146/luca-ferrari/postgresql/ch-2.sql
new file mode 100644
index 0000000000..39d2cd1aac
--- /dev/null
+++ b/challenge-146/luca-ferrari/postgresql/ch-2.sql
@@ -0,0 +1,145 @@
+DROP TABLE IF EXISTS fraction_tree;
+CREATE TABLE fraction_tree (
+ pk int GENERATED ALWAYS AS IDENTITY
+ , numerator int default 1
+ , denominator int default 1
+ , child_of int
+ , level int default 1
+ , PRIMARY KEY( pk )
+ , FOREIGN KEY (child_of) REFERENCES fraction_tree( pk )
+);
+
+
+TRUNCATE TABLE fraction_tree;
+ALTER TABLE fraction_tree ALTER COLUMN pk RESTART;
+
+
+INSERT INTO fraction_tree( numerator, denominator )
+VALUES( 1, 1 );
+
+
+
+
+
+CREATE OR REPLACE FUNCTION
+f_add_one_level_fraction_tree()
+RETURNS INT
+AS $CODE$
+DECLARE
+ current_left fraction_tree%rowtype;
+ current_right fraction_tree%rowtype;
+ previous_tuple fraction_tree%rowtype;
+ nodes_added int := 0;
+BEGIN
+
+ FOR previous_tuple IN SELECT * FROM fraction_tree
+ WHERE level = ( SELECT max( level ) FROM fraction_tree )
+ LOOP
+
+
+ current_left.numerator := previous_tuple.numerator;
+ current_left.denominator := ( previous_tuple.numerator + previous_tuple.denominator );
+ current_left.child_of := previous_tuple.pk;
+ current_left.level := previous_tuple.level + 1;
+ current_left.pk := nextval( 'fraction_tree_pk_seq' );
+
+ current_right.numerator := ( previous_tuple.numerator + previous_tuple.denominator );
+ current_right.denominator := previous_tuple.denominator;
+ current_right.child_of := previous_tuple.pk;
+ current_right.level := previous_tuple.level + 1;
+ current_right.pk := nextval( 'fraction_tree_pk_seq' );
+
+ INSERT INTO fraction_tree
+ OVERRIDING SYSTEM VALUE
+ SELECT current_left.*;
+
+ INSERT INTO fraction_tree
+ OVERRIDING SYSTEM VALUE
+ SELECT current_right.*;
+
+ nodes_added := nodes_added + 2;
+
+ END LOOP;
+
+ RETURN nodes_added;
+END
+$CODE$
+LANGUAGE plpgsql;
+
+
+
+CREATE OR REPLACE FUNCTION
+f_populate_fraction_tree( levels int default 4 )
+RETURNS int
+AS $CODE$
+DECLARE
+ i int := 0;
+ nodes_added int := 0;
+BEGIN
+ FOR i IN 1 .. levels LOOP
+ nodes_added := nodes_added + f_add_one_level_fraction_tree();
+ END LOOP;
+
+ RETURN nodes_added;
+END
+$CODE$
+LANGUAGE plpgsql;
+
+
+/*
+testdb=> select * from f_search_for_fraction_tree( 3, 5 );
+description | fraction
+-------------+----------
+child | 3/5
+parent | 3/2
+grandparent | 1/2
+
+*/
+
+CREATE OR REPLACE FUNCTION
+f_search_for_fraction_tree( numer int, denomin int )
+RETURNS TABLE ( description text, fraction text )
+AS $CODE$
+DECLARE
+ current_tuple fraction_tree%rowtype;
+BEGIN
+ SELECT 'child', numerator || '/' || denominator
+ INTO description, fraction
+ FROM fraction_tree
+ WHERE numerator = numer
+ AND denominator = denomin;
+
+ IF FOUND THEN
+ RETURN NEXT;
+
+
+ SELECT 'parent', numerator || '/' || denominator
+ INTO description, fraction
+ FROM fraction_tree
+ WHERE pk = ( SELECT child_of
+ FROM fraction_tree
+ WHERE numerator = numer
+ AND denominator = denomin );
+
+ RETURN NEXT;
+
+
+
+ SELECT 'grandparent', numerator || '/' || denominator
+ INTO description, fraction
+ FROM fraction_tree
+ WHERE pk = ( SELECT child_of
+ FROM fraction_tree
+ WHERE pk = ( SELECT child_of
+ FROM fraction_tree
+ WHERE numerator = numer
+ AND denominator = denomin ) );
+
+ RETURN NEXT;
+
+ END IF;
+
+ RETURN;
+END
+$CODE$
+LANGUAGE plpgsql;