-- Create the user-defined type for N-dimensional boxes
-- 
BEGIN TRANSACTION;

-- Adjust this setting to control where the objects get created.
SET search_path = public;

CREATE FUNCTION cube_in(opaque)
RETURNS opaque
AS 'MODULE_PATHNAME'
LANGUAGE 'c';

CREATE FUNCTION cube_out(opaque)
RETURNS opaque
AS 'MODULE_PATHNAME'
LANGUAGE 'c';

CREATE TYPE cube (
internallength = variable,
input = cube_in,
output = cube_out
);

COMMENT ON TYPE cube IS
'multi-dimensional cube ''(FLOAT-1, FLOAT-2, ..., FLOAT-N), (FLOAT-1, FLOAT-2, ..., FLOAT-N)''';

--
-- External C-functions for R-tree methods
--

-- Left/Right methods

CREATE FUNCTION cube_over_left(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_over_left(cube, cube) IS
'is over and left of (NOT IMPLEMENTED)';

CREATE FUNCTION cube_over_right(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_over_right(cube, cube) IS
'is over and right of (NOT IMPLEMENTED)';

CREATE FUNCTION cube_left(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_left(cube, cube) IS
'is left of (NOT IMPLEMENTED)';

CREATE FUNCTION cube_right(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_right(cube, cube) IS
'is right of (NOT IMPLEMENTED)';


-- Comparison methods

CREATE FUNCTION cube_lt(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_lt(cube, cube) IS
'lower than';

CREATE FUNCTION cube_gt(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_gt(cube, cube) IS
'greater than';

CREATE FUNCTION cube_contains(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_contains(cube, cube) IS
'contains';

CREATE FUNCTION cube_contained(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_contained(cube, cube) IS
'contained in';

CREATE FUNCTION cube_overlap(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_overlap(cube, cube) IS
'overlaps';

CREATE FUNCTION cube_same(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_same(cube, cube) IS
'same as';

CREATE FUNCTION cube_different(cube, cube) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

COMMENT ON FUNCTION cube_different(cube, cube) IS
'different';

-- support routines for indexing

CREATE FUNCTION cube_union(cube, cube) RETURNS cube
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

CREATE FUNCTION cube_inter(cube, cube) RETURNS cube
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

CREATE FUNCTION cube_size(cube) RETURNS float4
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);


-- Misc N-dimensional functions

-- proximity routines

CREATE FUNCTION cube_distance(cube, cube) RETURNS float4
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);


--
-- OPERATORS
--

CREATE OPERATOR < (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_lt,
   COMMUTATOR = '>',
   RESTRICT = scalarltsel, JOIN = scalarltjoinsel
);

CREATE OPERATOR > (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_gt,
   COMMUTATOR = '<',
   RESTRICT = scalargtsel, JOIN = scalargtjoinsel
);

CREATE OPERATOR << (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_left,
   COMMUTATOR = '>>',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR &< (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_over_left,
   COMMUTATOR = '&>',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR && (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_overlap,
   COMMUTATOR = '&&',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR &> (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_over_right,
   COMMUTATOR = '&<',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR >> (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_right,
   COMMUTATOR = '<<',
   RESTRICT = positionsel, JOIN = positionjoinsel
);

CREATE OPERATOR = (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_same,
   COMMUTATOR = '=', NEGATOR = '<>',
   RESTRICT = eqsel, JOIN = eqjoinsel,
   SORT1 = '<', SORT2 = '<'
);

CREATE OPERATOR <> (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_different,
   COMMUTATOR = '<>', NEGATOR = '=',
   RESTRICT = neqsel, JOIN = neqjoinsel
);

CREATE OPERATOR @ (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_contains,
   COMMUTATOR = '~',
   RESTRICT = contsel, JOIN = contjoinsel
);

CREATE OPERATOR ~ (
   LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_contained,
   COMMUTATOR = '@',
   RESTRICT = contsel, JOIN = contjoinsel
);


-- define the GiST support methods
CREATE FUNCTION g_cube_consistent(opaque,cube,int4) RETURNS bool
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_compress(opaque) RETURNS opaque 
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_decompress(opaque) RETURNS opaque 
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_penalty(opaque,opaque,opaque) RETURNS opaque
	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);

CREATE FUNCTION g_cube_picksplit(opaque, opaque) RETURNS opaque
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_union(bytea, opaque) RETURNS cube 
	AS 'MODULE_PATHNAME' LANGUAGE 'c';

CREATE FUNCTION g_cube_same(cube, cube, opaque) RETURNS opaque 
	AS 'MODULE_PATHNAME' LANGUAGE 'c';


-- Create the operator class for indexing

CREATE OPERATOR CLASS gist_cube_ops
    DEFAULT FOR TYPE cube USING gist AS
	OPERATOR	1	<< ,
	OPERATOR	2	&< ,
	OPERATOR	3	&& ,
	OPERATOR	4	&> ,
	OPERATOR	5	>> ,
	OPERATOR	6	= ,
	OPERATOR	7	@ ,
	OPERATOR	8	~ ,
	FUNCTION	1	g_cube_consistent (opaque, cube, int4),
	FUNCTION	2	g_cube_union (bytea, opaque),
	FUNCTION	3	g_cube_compress (opaque),
	FUNCTION	4	g_cube_decompress (opaque),
	FUNCTION	5	g_cube_penalty (opaque, opaque, opaque),
	FUNCTION	6	g_cube_picksplit (opaque, opaque),
	FUNCTION	7	g_cube_same (cube, cube, opaque);


END TRANSACTION;
