complex.source
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:11k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. ---------------------------------------------------------------------------
  2. --
  3. -- complex.sql-
  4. --    This file shows how to create a new user-defined type and how to
  5. --    use this new type.
  6. -- 
  7. --
  8. -- Copyright (c) 1994, Regents of the University of California
  9. --
  10. -- $Id: complex.source,v 1.4 1998/03/01 04:52:59 scrappy Exp $
  11. --
  12. ---------------------------------------------------------------------------
  13. -----------------------------
  14. -- Creating a new type:
  15. -- a user-defined type must have an input and an output function. They
  16. -- are user-defined C functions. We are going to create a new type 
  17. -- called 'complex' which represents complex numbers.
  18. -----------------------------
  19. -- Assume the user defined functions are in _OBJWD_/complex.so
  20. -- Look at $PWD/complex.c for the source.
  21. -- the input function 'complex_in' takes a null-terminated string (the 
  22. -- textual representation of the type) and turns it into the internal
  23. -- (in memory) representation. You will get a message telling you 'complex'
  24. -- does not exist yet but that's okay.
  25. CREATE FUNCTION complex_in(opaque)
  26.    RETURNS complex
  27.    AS '_OBJWD_/complex.so'
  28.    LANGUAGE 'c';
  29. -- the output function 'complex_out' takes the internal representation and
  30. -- converts it into the textual representation.
  31. CREATE FUNCTION complex_out(opaque)
  32.    RETURNS opaque
  33.    AS '_OBJWD_/complex.so'
  34.    LANGUAGE 'c';
  35. -- now, we can create the type. The internallength specifies the size of the
  36. -- memory block required to hold the type (we need two 8-byte doubles).
  37. CREATE TYPE complex (
  38.    internallength = 16, 
  39.    input = complex_in,
  40.    output = complex_out
  41. );
  42. -----------------------------
  43. -- Using the new type:
  44. -- user-defined types can be use like ordinary built-in types.
  45. -----------------------------
  46. -- eg. we can use it in a schema
  47. CREATE TABLE test_complex (
  48. a complex,
  49. b complex
  50. );
  51. -- data for user-defined type are just strings in the proper textual
  52. -- representation. 
  53. INSERT INTO test_complex VALUES ('(1.0, 2.5)', '(4.2, 3.55 )');
  54. INSERT INTO test_complex VALUES ('(33.0, 51.4)', '(100.42, 93.55)');
  55. SELECT * FROM test_complex;
  56. -----------------------------
  57. -- Creating an operator for the new type:
  58. -- Let's define an add operator for complex types. Since POSTGRES
  59. -- supports function overloading, we'll use + as the add operator.
  60. -- (Operators can be reused with different number and types of 
  61. -- arguments.)
  62. -----------------------------
  63. -- first, define a function complex_add (also in complex.c)
  64. CREATE FUNCTION complex_add(complex, complex)
  65.    RETURNS complex
  66.    AS '_OBJWD_/complex.so'
  67.    LANGUAGE 'c';
  68. -- we can now define the operator. We show a binary operator here but you
  69. -- can also define unary operators by omitting either of leftarg or rightarg.
  70. CREATE OPERATOR + ( 
  71.    leftarg = complex,
  72.    rightarg = complex,
  73.    procedure = complex_add,
  74.    commutator = +
  75. );
  76. SELECT (a + b) AS c FROM test_complex;
  77. -- Occasionally, you may find it useful to cast the string to the desired
  78. -- type explicitly. :: denotes a type cast.
  79. SELECT  a + '(1.0,1.0)'::complex AS aa,
  80.         b + '(1.0,1.0)'::complex AS bb
  81.    FROM test_complex;
  82. -----------------------------
  83. -- Creating aggregate functions
  84. -- you can also define aggregate functions. The syntax is somewhat
  85. -- cryptic but the idea is to express the aggregate in terms of state
  86. -- transition functions.
  87. -----------------------------
  88. CREATE AGGREGATE complex_sum (
  89.    sfunc1 = complex_add,
  90.    basetype = complex,
  91.    stype1 = complex,
  92.    initcond1 = '(0,0)'
  93. );
  94. SELECT complex_sum(a) FROM test_complex;
  95. -------------------------------------------------------------------------------
  96. --             ATTENTION!      ATTENTION!      ATTENTION!                    --
  97. --  YOU MAY SKIP THE SECTION BELOW ON INTERFACING WITH INDICES. YOU DON'T    --
  98. --  NEED THE FOLLOWING IF YOU DON'T USE INDICES WITH NEW DATA TYPES.         --
  99. -------------------------------------------------------------------------------
  100. SELECT 'READ ABOVE!' AS STOP;
  101. -----------------------------
  102. -- Interfacing New Types with Indices:
  103. -- We cannot define a secondary index (eg. a B-tree) over the new type
  104. -- yet. We need to modify a few system catalogs to show POSTGRES how
  105. -- to use the new type. Unfortunately, there is no simple command to
  106. -- do this. Please bear with me.
  107. -----------------------------
  108. -- first, define the required operators
  109. CREATE FUNCTION complex_abs_lt(complex, complex) RETURNS bool
  110.    AS '_OBJWD_/complex.so' LANGUAGE 'c';
  111. CREATE FUNCTION complex_abs_le(complex, complex) RETURNS bool
  112.    AS '_OBJWD_/complex.so' LANGUAGE 'c';
  113. CREATE FUNCTION complex_abs_eq(complex, complex) RETURNS bool
  114.    AS '_OBJWD_/complex.so' LANGUAGE 'c';
  115. CREATE FUNCTION complex_abs_ge(complex, complex) RETURNS bool
  116.    AS '_OBJWD_/complex.so' LANGUAGE 'c';
  117. CREATE FUNCTION complex_abs_gt(complex, complex) RETURNS bool
  118.    AS '_OBJWD_/complex.so' LANGUAGE 'c';
  119. -- the restrict and join selectivity functions are bogus (notice we only
  120. -- have intltsel, eqsel and intgtsel)
  121. CREATE OPERATOR < (
  122.    leftarg = complex, rightarg = complex, procedure = complex_abs_lt,
  123.    restrict = intltsel, join = intltjoinsel
  124. );
  125. CREATE OPERATOR <= (
  126.    leftarg = complex, rightarg = complex, procedure = complex_abs_le,
  127.    restrict = intltsel, join = intltjoinsel
  128. );
  129. CREATE OPERATOR = (
  130.    leftarg = complex, rightarg = complex, procedure = complex_abs_eq,
  131.    restrict = eqsel, join = eqjoinsel
  132. );
  133. CREATE OPERATOR >= (
  134.    leftarg = complex, rightarg = complex, procedure = complex_abs_ge,
  135.    restrict = intgtsel, join = intgtjoinsel
  136. );
  137. CREATE OPERATOR > (
  138.    leftarg = complex, rightarg = complex, procedure = complex_abs_gt,
  139.    restrict = intgtsel, join = intgtjoinsel
  140. );
  141. INSERT INTO pg_opclass VALUES ('complex_abs_ops');
  142. SELECT oid, opcname FROM pg_opclass WHERE opcname = 'complex_abs_ops';
  143. SELECT o.oid AS opoid, o.oprname
  144. INTO TABLE complex_ops_tmp
  145. FROM pg_operator o, pg_type t
  146. WHERE o.oprleft = t.oid and o.oprright = t.oid
  147.    and t.typname = 'complex';
  148. -- make sure we have the right operators
  149. SELECT * from complex_ops_tmp;
  150. INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, 
  151.                      amopselect, amopnpages)
  152.    SELECT am.oid, opcl.oid, c.opoid, 1,
  153. 'btreesel'::regproc, 'btreenpage'::regproc
  154.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  155.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  156.       and c.oprname = '<';
  157. INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, 
  158.                      amopselect, amopnpages)
  159.    SELECT am.oid, opcl.oid, c.opoid, 2,
  160. 'btreesel'::regproc, 'btreenpage'::regproc
  161.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  162.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  163.       and c.oprname = '<=';
  164. INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, 
  165.                      amopselect, amopnpages)
  166.    SELECT am.oid, opcl.oid, c.opoid, 3,
  167. 'btreesel'::regproc, 'btreenpage'::regproc
  168.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  169.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  170.       and c.oprname = '=';
  171. INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, 
  172.                      amopselect, amopnpages)
  173.    SELECT am.oid, opcl.oid, c.opoid, 4,
  174. 'btreesel'::regproc, 'btreenpage'::regproc
  175.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  176.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  177.       and c.oprname = '>=';
  178. INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, 
  179.                      amopselect, amopnpages)
  180.    SELECT am.oid, opcl.oid, c.opoid, 5,
  181. 'btreesel'::regproc, 'btreenpage'::regproc
  182.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  183.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  184.       and c.oprname = '>';
  185. --
  186. CREATE FUNCTION complex_abs_cmp(complex, complex) RETURNS int4
  187.    AS '_OBJWD_/complex.so' LANGUAGE 'c';
  188. SELECT oid, proname FROM pg_proc WHERE proname = 'complex_abs_cmp';
  189. INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
  190.    SELECT am.oid, opcl.oid, pro.oid, 1
  191.    FROM pg_am am, pg_opclass opcl, pg_proc pro
  192.    WHERE  amname = 'btree' and opcname = 'complex_abs_ops'
  193.       and proname = 'complex_abs_cmp';
  194. -- now, we can define a btree index on complex types. First, let's populate
  195. -- the table. Note that postgres needs many more tuples to start using the
  196. -- btree index during selects.
  197. INSERT INTO test_complex VALUES ('(56.0,-22.5)', '(-43.2,-0.07)');
  198. INSERT INTO test_complex VALUES ('(-91.9,33.6)', '(8.6,3.0)');
  199. CREATE INDEX test_cplx_ind ON test_complex
  200.    USING btree(a complex_abs_ops);
  201. SELECT * from test_complex where a = '(56.0,-22.5)';
  202. SELECT * from test_complex where a < '(56.0,-22.5)';
  203. SELECT * from test_complex where a > '(56.0,-22.5)';
  204. DELETE FROM pg_amop where (amopid, amopclaid, amopopr, amopstrategy)
  205.    = (
  206.    SELECT am.oid, opcl.oid, c.opoid, 1
  207.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  208.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  209.       and c.oprname = '<');
  210. DELETE FROM pg_amop where (amopid, amopclaid, amopopr, amopstrategy)
  211.    = (
  212.    SELECT am.oid, opcl.oid, c.opoid, 2
  213.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  214.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  215.       and c.oprname = '<=');
  216. DELETE FROM pg_amop where (amopid, amopclaid, amopopr, amopstrategy)
  217.    = (
  218.    SELECT am.oid, opcl.oid, c.opoid, 3
  219.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  220.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  221.       and c.oprname = '=');
  222. DELETE FROM pg_amop where (amopid, amopclaid, amopopr, amopstrategy)
  223.    = (
  224.    SELECT am.oid, opcl.oid, c.opoid, 4
  225.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  226.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  227.       and c.oprname = '>=');
  228. DELETE FROM pg_amop where (amopid, amopclaid, amopopr, amopstrategy)
  229.    = (
  230.    SELECT am.oid, opcl.oid, c.opoid, 5
  231.    FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
  232.    WHERE amname = 'btree' and opcname = 'complex_abs_ops' 
  233.       and c.oprname = '>');
  234. DELETE FROM pg_amproc where (amid, amopclaid, amproc, amprocnum)
  235.    = (
  236.    SELECT am.oid, opcl.oid, pro.oid, 1
  237.    FROM pg_am am, pg_opclass opcl, pg_proc pro
  238.    WHERE  amname = 'btree' and opcname = 'complex_abs_ops'
  239.       and proname = 'complex_abs_cmp');
  240. DELETE FROM pg_opclass WHERE opcname = 'complex_abs_ops';
  241. DROP FUNCTION complex_in(opaque);
  242. DROP FUNCTION complex_out(opaque);
  243. DROP FUNCTION complex_add(complex, complex);
  244. DROP FUNCTION complex_abs_lt(complex, complex);
  245. DROP FUNCTION complex_abs_le(complex, complex);
  246. DROP FUNCTION complex_abs_eq(complex, complex);
  247. DROP FUNCTION complex_abs_ge(complex, complex);
  248. DROP FUNCTION complex_abs_gt(complex, complex);
  249. DROP FUNCTION complex_abs_cmp(complex, complex);
  250. DROP OPERATOR + (complex, complex);
  251. DROP OPERATOR < (complex, complex);
  252. DROP OPERATOR <= (complex, complex);
  253. DROP OPERATOR = (complex, complex);
  254. DROP OPERATOR >= (complex, complex);
  255. DROP OPERATOR > (complex, complex);
  256. DROP AGGREGATE complex_sum complex;
  257. DROP TYPE complex;
  258. DROP TABLE test_complex, complex_ops_tmp;