File: udt.xml

package info (click to toggle)
virtuoso-opensource 7.2.5.1%2Bdfsg1-0.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 285,240 kB
  • sloc: ansic: 641,220; sql: 490,413; xml: 269,570; java: 83,893; javascript: 79,900; cpp: 36,927; sh: 31,653; cs: 25,702; php: 12,690; yacc: 10,227; lex: 7,601; makefile: 7,129; jsp: 4,523; awk: 1,697; perl: 1,013; ruby: 1,003; python: 326
file content (1592 lines) | stat: -rw-r--r-- 68,676 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
<?xml version="1.0" encoding="utf-8" ?>
<!--
 -  
 -  This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
 -  project.
 -  
 -  Copyright (C) 1998-2018 OpenLink Software
 -  
 -  This project is free software; you can redistribute it and/or modify it
 -  under the terms of the GNU General Public License as published by the
 -  Free Software Foundation; only version 2 of the License, dated June 1991.
 -  
 -  This program is distributed in the hope that it will be useful, but
 -  WITHOUT ANY WARRANTY; without even the implied warranty of
 -  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 -  General Public License for more details.
 -  
 -  You should have received a copy of the GNU General Public License along
 -  with this program; if not, write to the Free Software Foundation, Inc.,
 -  51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 -  
 -  
-->

<sect1 id="udt"><title>User Defined Types</title>

<para>A user-defined type is a schema object, identified by a user-defined
type name.  The definition of a user-defined type specifies a number of
components, including in particular a list of attribute definitions.  The
representation of a user-defined type is expressed as a list of attribute
definitions.</para>

<para>The definition of a user-defined type may include a method specification
list consisting of one or more method specifications.  A method specification
is either an original method specification or an overriding method
specification.  Each original method specification specifies the method name,
the SQL parameter declaration list, the returns data type, the &lt;language clause&gt;,
the language (if the language is not SQL), and whether it is a STATIC or
CONSTRUCTOR method.</para>

<para>Each overriding method specification specifies the method name, the SQL
parameter declaration list and the RETURNS data type.  For each overriding method
specification, there must be an original method specification with the same
method name and SQL parameter declaration list in some proper supertype of
the user-defined type.  Every SQL-invoked method in a schema must correspond to
exactly one original method specification or overriding method specification
associated with some user-defined type existing in that schema.  A
method <computeroutput>M</computeroutput> that corresponds to an original method
specification in the definition of a structured type <computeroutput>T1</computeroutput>
is an original method of <computeroutput>T1</computeroutput>. A
method <computeroutput>M</computeroutput> that corresponds to an overriding
method specification in the definition of <computeroutput>T1</computeroutput> is
an overriding method of <computeroutput>T1</computeroutput>.  A method
<computeroutput>M</computeroutput> is a method of type
<computeroutput>T1</computeroutput> if one of the following holds:</para>

<simplelist>
  <member><computeroutput>M</computeroutput> is an original method of <computeroutput>T1</computeroutput></member>
  <member><computeroutput>M</computeroutput> is an overriding method of <computeroutput>T1</computeroutput></member>
  <member>There is a proper supertype <computeroutput>T2</computeroutput> of
  <computeroutput>T1</computeroutput> such that <computeroutput>M</computeroutput>
  is an original or overriding method of <computeroutput>T2</computeroutput>
  and such that there is no method <computeroutput>M3</computeroutput> such that
  <computeroutput>M3</computeroutput> has the same method name and SQL parameter
  declaration list as <computeroutput>M</computeroutput> and
  <computeroutput>M3</computeroutput> is an original method or overriding
  method of a type <computeroutput>T3</computeroutput> such that
  <computeroutput>T2</computeroutput> is a proper supertype of
  <computeroutput>T3</computeroutput> and <computeroutput>T3</computeroutput> is
  a supertype of <computeroutput>T1</computeroutput>.</member>
</simplelist>

<para>A user defined type can be a direct subtype of one (and only one) user
defined type.  The user defined type cannot be a subtype of itself.</para>

<para>A type <computeroutput>Ta</computeroutput> is a direct subtype of a type
<computeroutput>Tb</computeroutput> if <computeroutput>Ta</computeroutput> is a
proper subtype of <computeroutput>Tb</computeroutput> and there does not exist a
type <computeroutput>Tc</computeroutput> such that <computeroutput>Tc</computeroutput>
is a proper subtype of <computeroutput>Tb</computeroutput> and a proper supertype
of <computeroutput>Ta</computeroutput>.</para>

<para>A type <computeroutput>Ta</computeroutput> is a subtype of type
<computeroutput>Tb</computeroutput> if one of the following pertains:</para>

<simplelist>
  <member><computeroutput>Ta</computeroutput> is a direct subtype of
  <computeroutput>Tb</computeroutput>; or</member>
  <member><computeroutput>Ta</computeroutput> is a subtype of some type
  <computeroutput>Tc</computeroutput> and <computeroutput>Tc</computeroutput> is
  a direct subtype of <computeroutput>Tb</computeroutput>.</member>
</simplelist>

<para>By the same token, <computeroutput>Tb</computeroutput> is a supertype of
<computeroutput>Ta</computeroutput> and is a direct supertype of
<computeroutput>Ta</computeroutput> in the particular case where
<computeroutput>Ta</computeroutput> is a direct subtype of
<computeroutput>Tb</computeroutput>.  If <computeroutput>Ta</computeroutput>
is a subtype of <computeroutput>Tb</computeroutput>, then
<computeroutput>Ta</computeroutput> is proper subtype of
<computeroutput>Tb</computeroutput> and <computeroutput>Tb</computeroutput> is
a proper supertype of <computeroutput>Ta</computeroutput>.  A type cannot be a
proper supertype of itself.  A type with no proper supertypes is a maximal
supertype.  A type with no proper subtypes is a leaf type.</para>

<para>Let <computeroutput>Ta</computeroutput> be a maximal supertype and let
<computeroutput>T</computeroutput> be a subtype of <computeroutput>Ta</computeroutput>.
The set of all subtypes of <computeroutput>Ta</computeroutput> (which includes
<computeroutput>Ta</computeroutput> itself) is called a subtype family of
<computeroutput>T</computeroutput> or (equivalently) of
<computeroutput>Ta</computeroutput>.  A subtype family is not permitted to have
more than one maximal supertype.  Every value in a type
<computeroutput>T</computeroutput> is a value in every supertype of
<computeroutput>T</computeroutput>.  A value <computeroutput>V</computeroutput>
in type <computeroutput>T</computeroutput> has exactly one most specific type
<computeroutput>MST</computeroutput> such that <computeroutput>MST</computeroutput>
is a subtype of <computeroutput>T</computeroutput> and
<computeroutput>V</computeroutput> is not a value in any proper subtype of
<computeroutput>MST</computeroutput>.  The most specific type of value need not
be a leaf type.  For example, a type structure might consist of a type
<computeroutput>PERSON</computeroutput> that has
<computeroutput>STUDENT</computeroutput> and <computeroutput>EMPLOYEE</computeroutput>
as its two subtypes, while <computeroutput>STUDENT</computeroutput> has two
direct subtypes <computeroutput>UG_STUDENT</computeroutput> and
<computeroutput>PG_STUDENT</computeroutput>.  The invocation
<computeroutput>STUDENT( )</computeroutput> of the constructor function for
<computeroutput>STUDENT</computeroutput> returns a value whose most specific
type is <computeroutput>STUDENT</computeroutput>, which is not a leaf type.
If <computeroutput>Ta</computeroutput> is a subtype of
<computeroutput>Tb</computeroutput>, then a value in
<computeroutput>Ta</computeroutput> can be used wherever a value in
<computeroutput>Tb</computeroutput> is expected. In particular, a value in
<computeroutput>Ta</computeroutput> can be stored in a column of type
<computeroutput>Tb</computeroutput>, can be substituted as an argument for an
input SQL parameter of data type <computeroutput>Tb</computeroutput>, and can
be the value of an invocation of an SQL-invoked function whose result data type
is <computeroutput>Tb</computeroutput>.  A type <computeroutput>T</computeroutput>
is said to be the minimal common supertype of a set of types
<computeroutput>S</computeroutput> if <computeroutput>T</computeroutput> is a
supertype of every type in <computeroutput>S</computeroutput> and a subtype of
every type that is a supertype of every type in <computeroutput>S</computeroutput>.</para>

<note><title>Note:</title>
<para>Because a subtype family has exactly one maximal supertype, if two types
have a common subtype, they must also have a minimal common supertype.  Thus,
for every set of types drawn from the same subtype family, there is some member
of that family that is the minimal common supertype of all of the types in that
set.  </para></note>

<para>A user-defined type is declared by a user-defined type
<link linkend="udtcreatetypestmt">CREATE TYPE statement</link>.</para>

<sect2 id="udtcreatetypestmt"><title>CREATE TYPE Statement</title>

<programlisting><![CDATA[
CREATE TYPE type_name
   [ UNDER type_name ]
   [ LANGUAGE language_name [ EXTERNAL NAME literal ] ]
   [ AS (type_member, ...) ]
   [ type_option [type option ] .... ]
   [ method_specification, ... ]

type_name :
  [ [ identifier  .] [ identifier ] . ] identifier

type_member :
  identifier data_type [ DEFAULT literal ] [ EXTERNAL NAME string ] [ EXTERNAL TYPE string ]
    [ __SOAP_TYPE literal ] [ __SOAP_NAME literal ]

type_option : SELF AS REF | TEMPORARY | SOAP_TYPE literal

method_specification : original_method_specification | overriding_method_specification

original_method_specification :
  [ STATIC | INSTANCE ] METHOD identifier ( [ decl_parameter, ... ] )
    RETURNS data_type [ method_characteristics ]
  |
  CONSTRUCTOR METHOD identifier ( [ decl_parameter, ... ] )  [ method_characteristics ]

overriding_method_specification :
	OVERRIDING [ INSTANCE ] METHOD identifier ( [ decl_parameter, ... ] )
    RETURNS data_type

method_characteristics :
  [ EXTERNAL TYPE literal ] [ EXTERNAL NAME string | EXTERNAL VARIABLE NAME string ]

language_name : SQL | CLR | JAVA
]]></programlisting>

<para>The CREATE TYPE statements declares a user defined type.  Generally
speaking the user defined types can be in two states: forward-referenced,
declared and instantiable.</para>

<para>A type is in forward reference state if it's name is quoted in some other
CREATE TYPE statement (as a supertype, member type or a method parameter type
or return type).  When a type is in forward reference state it's instances can be
copied, passed as parameter values and returned by functions, but it cannot be
instantiated, no type members can be accessed and no type methods can be called.
Forward references are temporary objects and they disappear at server shutdown.</para>

<para>A type moves to the declared state when a CREATE TYPE is executed for it.
In that state type methods can be called, type members can be accessed, but the type
cannot be instantiated.</para>

<para>A type goes into instantiable state from declared state when it has no
supertype or it's supertype is also in instantiable state.  The server tries to
move the defined types to instantiable state on every CREATE TYPE statement.</para>

<para>Normally the type definitions are stored into the DB.DBA.SYS_USER_TYPES
system table.</para>

<para>This has the following layout:</para>

<programlisting>
CREATE TABLE SYS_USER_TYPES
(
 UT_NAME VARCHAR,
 UT_PARSE_TREE LONG VARCHAR,
 UT_ID integer identity,
 UT_MIGRATE_TO integer,
 primary key (UT_NAME));
</programlisting>

<simplelist>
 <member><emphasis>UT_NAME</emphasis> - the fully qualified user defined type name.</member>
 <member><emphasis>UT_PARSE_TREE</emphasis> - the user defined type definition (in machine readable form).</member>
 <member><emphasis>UT_ID</emphasis> - the ID of the type (used in persisting type instances to/from network/storage).</member>
 <member><emphasis>UT_MIGRATE_TO</emphasis> - reserved for future use.</member>
</simplelist>

<para>If a TEMPORARY type_option is specified, the CREATE TYPE does not write
the type definition into the table - it declares the type only in server's
memory.  TEMPORARY types are not persistable.  They disappear when the server is
restarted.  A TEMPORARY type cannot be a supertype or a subtype of a
non-TEMPORARY type.</para>

<para>The <computeroutput>SELF AS REF</computeroutput> option directs the server
to return a reference to the type's instance when instantiating the type, as
opposed to returning the instance itself.  The references are explained in
more detail in the <computeroutput>NEW</computeroutput> operator.</para>

<note><title>Note:</title>
<para>The CREATE TYPE is an autocommitting statement.</para></note>

<example id="ex_createtype"><title>Creating User Defined Types</title>
<para>This example creates a SQL implemented user defined type UDT_TEST with
no supertype.  It has two members : A and B, two constructor methods, a static
method _ADD, an ADDIT method taking either zero or two arguments and an instance
method SUB_IT.</para>

<programlisting><![CDATA[
create type UDT_TEST
  as (A integer default 1, B integer default 2)
  CONSTRUCTOR METHOD UDT_TEST(_a integer, _b integer),
  CONSTRUCTOR METHOD UDT_TEST(),
  STATIC METHOD _ADD(_xx integer, _yy integer) returns integer specific DB.DBA.static_add,
  METHOD ADDIT() returns integer,
  METHOD ADDIT(c integer) returns integer,
  METHOD SUB_IT () returns integer;
]]></programlisting>

<para>This creates a subtype of UDT_TEST named UDT_TEST_SUB.  UDT_TEST_SUB
extends the static method _ADD of UDT_TEST so it can also take 4 arguments,
overrides the method ADDIT from UDT_TEST and defines a new instance method
MULTIPLY_IT.</para>

<programlisting><![CDATA[
create type UDT_TEST_SUB under UDT_TEST
  as (C integer default 12, _D integer default 32)
  STATIC METHOD _ADD(_xx integer, _yy integer, _zz integer, _qq integer) returns integer,
  OVERRIDING METHOD ADDIT() returns integer,
  METHOD MULTIPLY_IT () returns integer;
]]></programlisting>

<para>This is a SQL wrapper for a public Java type testsuite_base
(see testsuite_base.java).</para>

<programlisting><![CDATA[
create type testsuite_base language java external name 'testsuite_base'
as (
    protected_I integer external name 'protected_I' external type 'I',
    private_I integer external name 'private_I' external type 'I',
    sZ smallint external name 'Z' external type 'Z',
    sfalseZ smallint external name 'falseZ' external type 'Z',
    sB smallint external name 'B' external type 'B',
    sC smallint external name 'C' external type 'C',
    sS smallint external name 'S' external type 'S',
    sI int external name 'I' external type 'I',
    sJ int external name 'J' external type 'J',
    sF real external name 'F' external type 'F',
    sD double precision external name 'D' external type 'D',
    sL any external name 'L' external type 'Ljava/lang/Short;',
    sAI any external name 'AI' external type '[I',
    sAL any external name 'AL' external type '[Ljava/lang/Short;',
    sstr nvarchar external name 'str' external type 'Ljava/lang/String;',
    sdat datetime external name 'dat' external type 'Ljava/util/Date;',

    tF real external name 'F',
    "F" real,

    non_existant_var integer external name 'non_existant_var' external type 'I'
   )
    static method get_static_ro_I ()
	returns integer external type 'I' external variable name 'static_ro_I',
    static method get_static_I ()
	returns integer external type 'I' external variable name 'static_I',
    static method get_protected_static_I ()
	returns integer external type 'I' external variable name 'protected_static_I',
    static method get_private_static_I ()
	returns integer external type 'I' external variable name 'private_static_I',

    static method test_bool (x integer external type 'I')
	returns smallint external type 'Z' external name 'test_bool',

    constructor method testsuite_base (),
    constructor method testsuite_base (i integer external type 'I'),

    static method echoDouble (a double precision external type 'D')
	returns any external type 'Ljava/lang/Double;' external name 'echoDouble',
    static method getObjectType (a any external type 'Ljava/lang/Object;')
	returns varchar external type 'Ljava/lang/String;' external name 'getObjectType',
    static method echoThis (a testsuite_base external type 'Ltestsuite_base;')
	returns integer external type 'I' external name 'echoThis',
    static method static_echoInt (a integer external type 'I')
	returns integer external type 'I' external name 'static_echoInt',

    static method change_it (a testsuite_base)
	returns integer external type 'I' external name 'change_it',

    method "overload_method" (i integer external type 'I')
	returns integer external type 'I',

    method echoInt (a integer external type 'I')
	returns integer external type 'I' external name 'echoInt',

    method echoInt (a double precision external type 'D')
	returns integer external type 'I' external name 'echoInt',

    method protected_echo_int (a integer external type 'I')
	returns integer external type 'I' external name 'protected_echo_int',

    method private_echo_int (a integer external type 'I')
	returns integer external type 'I' external name 'private_echo_int',

    method "echoDbl" (a double precision)
	returns double precision,

    method non_existant_method (a integer external type 'I')
	returns integer external type 'I' external name 'non_existant_method',

    static method non_existant_static_var (a integer external type 'I')
	returns integer external type 'I' external variable name 'non_existant_static_var';
]]></programlisting>
</example>
</sect2>

<sect2 id="udtaltertypestmt"><title>ALTER TYPE Statement</title>

<programlisting><![CDATA[
ALTER TYPE type_name
 (  ADD ATTRIBUTE type_member
 | DROP ATTRIBUTE identifier [ CASCADE | RESTRICT ]
 | ADD method_specification
 | DROP original_method_specification [ CASCADE | RESTRICT ]

type_name :
  [ [ identifier  .] [ identifier ] . ] identifier

type_member :
  identifier data_type [ DEFAULT literal ] [ EXTERNAL NAME string ] [ EXTERNAL TYPE string ]
    [ __SOAP_TYPE literal ] [ __SOAP_NAME literal ]

type_option : SELF AS REF | TEMPORARY | SOAP_TYPE literal

method_specification : original_method_specification | overriding_method_specification

original_method_specification :
  [ STATIC | INSTANCE ] METHOD identifier ( [ decl_parameter, ... ] )
    RETURNS data_type [ method_characteristics ]
  |
  CONSTRUCTOR METHOD identifier ( [ decl_parameter, ... ] )  [ method_characteristics ]

overriding_method_specification :
	OVERRIDING [ INSTANCE ] METHOD identifier ( [ decl_parameter, ... ] )
    RETURNS data_type

method_characteristics :
  [ EXTERNAL TYPE literal ] [ EXTERNAL NAME string | EXTERNAL VARIABLE NAME string ]

language_name : SQL | CLR | JAVA
]]></programlisting>

<para>The ALTER TYPE statements modifies a user defined type.  It can be used for
    adding or dropping methods and members of user defined types.</para>


<note><title>Note:</title>
<para>The ALTER TYPE is an autocommitting statement.</para></note>

<example id="ex_altertype"><title>Altering User Defined Types</title>
<para>This example uses a SQL implemented user defined type UDT_ALTER_TYPE with
    no supertype defined as follows: </para>

<programlisting><![CDATA[
create type UDT_ALTER_TYPE as (A integer default 1)
method m1 (I integer) returns integer;
create method M1 (in I integer) returns integer for UDT_ALTER_TYPE
{
 return I;
};
]]></programlisting>

<para>Then it adds an attribute B to it :</para>

<programlisting><![CDATA[
alter type UDT_ALTER_TYPE Add attribute B integer default 2;
]]></programlisting>

<para>Then drops the original A attribute : </para>

<programlisting><![CDATA[
alter type udt_ALTER_TYPE drop attribute A;
]]></programlisting>

<para>Now let's add a new method M2 to the type : </para>

<programlisting><![CDATA[
alter type UDT_ALTER_TYPE Add method M2 (ID integer) returns integer;
create method M2 (in ID integer) returns integer for UDT_ALTER_TYPE
{
  return ID + 100;
};
]]></programlisting>

<para>And drop the M1 method : </para>

<programlisting><![CDATA[
alter type UDT_ALTER_TYPE drop method M1 (ID integer) returns integer;
]]></programlisting>
</example>
</sect2>

<sect2 id="udtdroptypestmt"><title>DROP TYPE Statement</title>

<programlisting>
DROP TYPE type_name
</programlisting>

<para>This statement reverses the effect of CREATE TYPE statement.  If the type
has methods defined they are deleted as well.  Note that forward references
cannot be dropped by a DROP TYPE.</para>
<para>The DROP TYPE statement can be used only for dropping types that are
not referenced in another type's UNDER statement.</para>

<example id="ex_udtdroptype"><title>Dropping a user-defined type</title>
<para>Dropping the subtype from the previous section.</para>
<programlisting><![CDATA[
drop type UDT_TEST_SUB;
]]></programlisting>
</example>
</sect2>


<sect2 id="udtcreatemethodstmt"><title>CREATE METHOD Statement</title>

<programlisting><![CDATA[
CREATE [ INSTANCE | STATIC | CONSTRUCTOR ] METHOD identifier
     ( parameter, .... ) [ RETURNS data_type ] FOR type_name
     {
       .....
     }

  parameter : { IN | OUT | INOUT } identifier data_type
]]></programlisting>

<para>For the SQL user defined types every method should be defined in order
to be callable.  It is an error to call CREATE METHOD for a non-SQL type's
methods (as the methods are implemented in some other non-SQL language).</para>

<para>There is no DROP METHOD as each CREATE METHOD will override the current
method definition (if any).  The method name, parameter types and the return
type should match exactly the method declaration (method_specification in
CREATE TYPE).</para>

<para>The method name for the constructors is the name of the type (without
the qualifier and the owner).</para>

<para>For the constructor and instance methods there is a variable named
<computeroutput>SELF</computeroutput> (in scope for the compound statement
defining the method) representing the current type instance.</para>

<para>The method members and other methods are not in scope in the method's
compound statement.  They should be accessed through the
<computeroutput>SELF</computeroutput> variable.</para>

<example id="ex_methodcreation"><title>Simple method demonstration</title>
<para>This example defines the two parameter constructor for the UDT_TEST type.
It sets the values for the type members A and B to the values of the constructor
parameters.  This example uses the SQL200n syntax for method mutators (see below).</para>

<programlisting><![CDATA[
create constructor method UDT_TEST (in _a integer, in _b integer)
  for UDT_TEST
{
  SELF := A(SELF, _a);
  SELF := B(SELF, _b);
  return SELF;
};
]]></programlisting>

<para>This defines the static method _ADD for the type UDT_TEST.
Note that it does not use SELF - it would be a syntax error to do so.</para>

<programlisting><![CDATA[
create static method _ADD (in a1 integer, in a2 integer)
  for UDT_TEST
{
  return a1 + a2;
};
]]></programlisting>
</example>
</sect2>

<sect2 id="udttypeinstances"><title>Type Instances</title>

<para>Every user defined type can have zero or more instances.  Every instance knows
it's type.  The instances are SQL values.  They are copyable.  Instances for SQL
types contain placeholders for the type's members.  Instances for non-SQL
types contain a reference to the real instance in type's hosted environment.
(Java VM for JAVA and the CLR virtual machine for CLR).  So copying an
instance is different for SQL and non-SQL types.  When a SQL type's instance
is copied a new set of members placeholders is created and all members values are
copied.  This way the copy does not hold any link to it's original and they can
be considered as two different instances.  This means that changing members'
value in the copy will not affect the original.</para>

<para>The non-SQL types instances hold only a reference to the real instance.
So copying such an instance is equivalent of making another reference to the
foreign object.  Thus changing the member's value in the copy WILL affect the
original.  Usually the foreign virtual machines have a means of explicitly
copying an instance, but they are not used by the Virtuoso server when copying
the SQL values.</para>

<para>As with the other SQL values, an instance gets destroyed when it is no
longer referenced.</para>
</sect2>

<sect2 id="udtinstancerefs"><title>Instance References</title>

<para>Because the SQL types instances cannot be referenced by more than one
variable/type member Virtuoso PL implements instance references.  The
references are created for the types marked with
<computeroutput>SELF AS REF type_option</computeroutput>
(see <link linkend="udtcreatetypestmt">CREATE TYPE</link>).  For such types the
constructor(s) make a SQL value of reference type in addition to making the
instance itself.  The engine places the instances in a connection specific
cache of instances and returns a SQL value of type reference which points to
that instance.  Copying the reference value will not cause copying the instance
into the cache, so a <computeroutput>SELF AS REF</computeroutput> type will behave
as a hosted class with respect to changing values in the copy.  A new instance in
the cache will be created only when the constructor for the type is called again.
The server will accept a SQL reference value in every place where an instance
value is expected.  When a reference is serialized, as in when storing into a
column of a table, the server will serialize the instance data, not the
reference itself.</para>

<para>The connection's instance cache is cleared after the completion of the
current server operation, i.e. completion of the top level state, statement
invoked by a client or the completion of processing an HTTP request.  The cache
will thus survive multiple transactions if these are transacted within a single
client initiated operation.</para>
</sect2>

<sect2 id="udtnewop"><title>NEW Operator</title>

<programlisting><![CDATA[
[ NEW ] type_name ( [ parameter_value, .... ] )
]]></programlisting>

<para>This returns an instance (or reference to an instance) of the user defined
type type_name.  It will try to match a constructor by calculating the parameter
types at compile time and matching the so produced signature to the closest
constructor signature (see below: <link linkend="udtfindingmethods">finding
methods</link>).  The SQL types have an implicit constructor with no parameters
that assigns the DEFAULT values to the type members (if any, otherwise NULL).
When a SQL constructor is called it will have the <computeroutput>SELF</computeroutput>
set-up to the result of calling the  implicit constructor.  The NEW operator
is a scalar expression and can be used wherever the SQL syntax allows scalar
expressions.</para>
</sect2>

<sect2 id="udtfindingmethods"><title>Finding Methods - Method Signatures Generation &amp; Comparison</title>

<para>A method of a user defined type is identified uniquely by the combination
of the following:</para>

<simplelist>
  <member>the method name</member>
  <member>number of the method's parameters</member>
  <member>the method's parameter types</member>
  <member>the method's return type</member>
</simplelist>

<para>This combination of a method attributes is called the method's signature.</para>

<para>The Virtuoso Server must know the method's types of the parameter values
and the return type at compile time to calculate the method signature and find
exactly the method to call in the types method table.  This is different from
the current practice in calling stored procedures, because the compile types
are not used to find the procedure.</para>

<para>The majority of the system functions are known at compile time to return
values of a certain SQL type (e.g.: LEFT is known to return VARCHAR,
ATOI returns INTEGER etc).  But there are some (e.g.: AREF) that may return
values of more than one type.  The Virtuoso server does type arithmetic
for scalar expressions at compile time already (to be able to supply columns
types of a result set to ODBC clients for example), but so far the calculated
type has only informative value and was not used anywhere during the compilation.
All of the type checks are done at runtime.  The method/constructor invocation
breaks that practice by using the calculated compile time types for the scalar
expressions.</para>

<example id="ex_udtpoorsignature"><title>Method Signatures</title>

<para>Consider a method <computeroutput>m1</computeroutput> of type
<computeroutput>t1</computeroutput> taking an INTEGER parameter and returning
an integer value:</para>

<programlisting><![CDATA[
CREATE METHOD m1 (in x integer)
  for t1 returns integer
{ return x + 10; };
]]></programlisting>

<para>Now consider calling the method as follows (in a Virtuoso/PL procedure):</para>

<programlisting>
...
declare p float;
declare ret integer;
declare t1i t1;

t1i := new t1();
p := 1;

ret := t1i.m1(p);
....
</programlisting>

<para>This will yield a compilation error explaining that there is no method
<computeroutput>m1</computeroutput> of user defined type <computeroutput>t1</computeroutput>.
It will do that because p has a compile time type of FLOAT.</para>
<para>The following will also fail to compile:</para>

<programlisting>
...
declare p integer;
declare ret float;
declare t1i t1;

t1i := new t1();
p := 1;

ret := t1i.m1(p);
....
</programlisting>

<para>This time the <computeroutput>ret</computeroutput> has a declared type of
FLOAT and there is no method in t1 taking 1 INTEGER parameter and returning FLOAT.</para>

<para>The most consistent way of specifying the compile time type of a scalar
expression is to enclose it in a CAST statement, as follows:</para>

<programlisting>
...
declare p float;
declare ret integer;
declare t1i t1;

t1i := new t1();
p := 1;

ret := t1i.m1(CAST (p as integer));
....
</programlisting>

<para>This will compile and execute correctly.</para>
</example>
</sect2>

<sect2 id="udtgetsetmembervals"><title>Getting &amp; Setting Member Values of Type Instances (member observers &amp; mutators)</title>

<para>Let <computeroutput>T</computeroutput> be a user defined type that has a
member <computeroutput>A</computeroutput> of type <computeroutput>AT</computeroutput>.
Let <computeroutput>IT</computeroutput> be an instance of type
<computeroutput>T</computeroutput>.</para>

<sect3 id="udtmemobserv"><title>Member Observers (Getting Values)</title>
  <para>There are two alternative syntaxes (both scalar expressions):</para>
  <programlisting><![CDATA[
SQL200n :  A(<scalar_exp>)
Virtuoso extension :  <scalar_exp>.A
]]></programlisting>

  <para>Both of the above will return a copy of the member's value of the
  instance in &lt;scalar_exp&gt; when the scalar expression &lt;scalar_exp&gt;
  has a compile time type of <computeroutput>T</computeroutput>.  If the compile
  time type is not determined to be a user defined type
  <computeroutput>T</computeroutput> the first one will be compiled as a call
  to the SQL function <computeroutput>A</computeroutput> and the second will
  either generate a syntax error or the server will consider it as reference
  to a scope variable (depending on the type of &lt;scalar_exp&gt;).</para>

  <para>These are also scalar expressions and have a compile time
  type <computeroutput>AT</computeroutput>.</para>

  <para>To specify an explicit type of the scalar expression there is a
  third syntax:</para>

  <programlisting><![CDATA[
(<scalar_exp> as T).A
]]></programlisting>

  <para>This will force the server to compile a reference to the member
  <computeroutput>A</computeroutput> in user defined type <computeroutput>T</computeroutput>.
  Whether the &lt;scalar_exp&gt; is indeed of type <computeroutput>T</computeroutput>
  will be checked at runtime.</para>
  </sect3>

<sect3 id="udtmemmutators"><title>Member Mutators (Setting Values)</title>
  <para>There are two alternative syntaxes (both scalar expressions):</para>

  <programlisting><![CDATA[
SQL200n :  A(<scalar_exp>, <new_value_scalar_exp>)
Virtuoso extension :  <scalar_exp>.A := <new_value_scalar_exp>
]]></programlisting>

  <para>Both of the above will set the member's value of the instance  in
  &lt;scalar_exp&gt; to a copy of &lt;new_value_scalar_exp&gt; when the
  scalar expression &lt;scalar_exp&gt; has a compile time type of
  <computeroutput>T</computeroutput>.  If the compile time type is not
  determined to be a user defined type <computeroutput>T</computeroutput> the
  first one will be compiled as a call to the SQL function
  <computeroutput>A</computeroutput> and the second will either generate
  a syntax error or the server will consider it as reference to a scope variable
  (depending on the type of &lt;scalar_exp&gt;).</para>

  <para>These are also scalar expressions and have a compile time type
  <computeroutput>T</computeroutput> and return a copy of the &lt;scalar_exp&gt;.
  To specify an explicit type of the scalar exp there is a third syntax:</para>

  <programlisting><![CDATA[
(<scalar_exp> as T).A := <new_value_scalar_exp>
]]></programlisting>

  <para>This will force the server to compile a reference to the member
  <computeroutput>A</computeroutput> in user defined type <computeroutput>T</computeroutput>.
  Whether the &lt;scalar_exp&gt; is indeed of type
  <computeroutput>T</computeroutput> will be checked at runtime.</para>

  <example id="ex_usingconstructor"><title>Member Construction</title>
  <para>This will make a new object of type <computeroutput>UDT_FR_BASE</computeroutput>
  by calling it's two int parameters constructor and will return the member
  <computeroutput>B</computeroutput> value of the instance stored in member
  <computeroutput>UDT_M</computeroutput> of <computeroutput>UDT_FR_BASE</computeroutput>.</para>

  <programlisting><![CDATA[
select new UDT_FR_BASE (1, 2).UDT_M.B;
]]></programlisting>
</example>
  </sect3>
</sect2>

<sect2 id="udtstaticmethods"><title>Calling Static Methods</title>
<para>Let <computeroutput>T</computeroutput> be a user defined type that has
a static method <computeroutput>SM</computeroutput>.</para>

<programlisting>
T::SM ( [ parameter, .... ] )
</programlisting>

<para>This will call the static method of <computeroutput>SM</computeroutput>
of <computeroutput>T</computeroutput> and will return whatever the static
method returns.</para>

<example id="ex_callstaticmethod"><title>Calling A Static Method</title>
<programlisting>
select UDT_TEST::_ADD (1, 2);
</programlisting>
</example>
</sect2>

<sect2 id="udtcallinstmethod"><title>Calling Instance Methods</title>
<para>Let <computeroutput>T</computeroutput> be a user defined type that has
an instance method <computeroutput>IM</computeroutput>.  Let
<computeroutput>IT</computeroutput> be a scalar expression having a compile
time type of <computeroutput>T</computeroutput>.</para>

<programlisting>
IT.IM ( [ parameter, .... ] )
</programlisting>

<para>This will call the instance method <computeroutput>IM</computeroutput>
of <computeroutput>T</computeroutput> and will return  whatever the
<computeroutput>IM</computeroutput> returns.</para>

<para>Similarly to  member observers/mutators the compile time type of
<computeroutput>IT</computeroutput> can be specified explicitly:</para>

<programlisting>
(IT as T).IM ( [ parameter, .... ] )
</programlisting>

<para>This syntax however has an additional property in that it will call the
method of the type regardless of whether it is overloaded in a subtype or not.
Let <computeroutput>ST</computeroutput> be a subtype of <computeroutput>T</computeroutput>
and <computeroutput>ST</computeroutput> that has the method
<computeroutput>IM</computeroutput> overloaded.  Let <computeroutput>IST</computeroutput>
be a scalar expression that represents an instance of <computeroutput>ST</computeroutput>.</para>

<para>Then:</para>

<programlisting>
(IST as T).IM ( [ parameter, ... ] )
</programlisting>

<para>will call the method <computeroutput>IM</computeroutput> as defined in
<computeroutput>T</computeroutput>, whereas</para>

<programlisting>
IST.IM ( [ parameter, ... ] )
</programlisting>

<para>will call the method <computeroutput>IM</computeroutput> as defined in
<computeroutput>ST</computeroutput>.</para>

<example id="ex_callinginstmethods"><title>Calling Overloaded Instance Methods</title>
<programlisting>
<![CDATA[
CREATE TYPE UDT_BASE
  method A () returns integer;

CREATE TYPE UDT_SUB under UDT_BASE
  OVERRIDING method A () returns integer;

create method A () returns integer for UDT_BASE
{
  return 1;
}

create method A () returns integer for UDT_SUB
{
  return 2;
}

select new UDT_SUB ().A() as IMPLICIT,
  (new UDT_SUB() as UDT_BASE).A() as EXPLICIT;
]]></programlisting>
<para>This will return:</para>
<programlisting><![CDATA[
IMPLICIT		EXPLICIT
----------------------------
2			1
]]></programlisting>

<para>This is done so the overloaded methods can call the base type methods.</para>
</example>
</sect2>

<sect2 id="udtserilizingtypeinst"><title>Serializing &amp; Deserializing Type Instances</title>
<para>Virtuoso allows serializing and deserializing of non TEMPORARY type
instances.  This means that the instances can be saved as a column value and can
be used with the serialize/deserialize SQL functions.</para>

<example id="ex_serializetypeinst"><title>Storing User Defined Types</title>
<para>This creates a type SER_UDT, a table UDT_TABLE with a DATA column
capable of storing SER_UDT instances, stores an instance of SER_UDT into the
table and demonstrates some selects using the stored instance.</para>

<programlisting><![CDATA[
create type SER_UDT as (A integer default 12)
  method NEGATE () returns integer;

create method NEGATE () returns integer for SER_UDT
{
  return SELF.A * -1;
}

create table UDT_TABLE (ID integer primary key, DATA SER_UDT);

insert into UDT_TABLE (ID, DATA) values (1, new SER_UDT ());

select C.DATA.A from UDT_TABLE C where C.ID = 1;

select C.ID from UDT_TABLE C where C.DATA.A > 10;

select C.ID from UDT_TABLE C where C.DATA.NEGATE() < -10;
]]></programlisting>

<para>Note that the table alias is mandatory here.</para>

<programlisting><![CDATA[
select ID from UDT_TABLE where DATA.A > 10;
]]></programlisting>

<para>and</para>

<programlisting><![CDATA[
select ID from UDT_TABLE where DATA.NEGATE() < -10;
]]></programlisting>

<para>will both yield a syntax error.</para>
</example>

<para>The columns of a certain type allow storing subtype instances as well.
The subtype instances will not be converted to the their supertype when stored.
</para>

<para>If we define the type <computeroutput>SER_UDT_SUB</computeroutput> as:</para>

<programlisting>
create type SER_UDT_SUB under SER_UDT
  as (B integer default 13);
</programlisting>

<para>then we can do:</para>

<programlisting>
insert into UDT_TABLE (ID, DATA) values (2, new SER_UDT_SUB ());

select (C.DATA as SER_UDT_SUB).B from UDT_TABLE C where C.ID = 2;
</programlisting>

<para>Type instances can be stored into an ANY column:</para>

<programlisting>
create table ANY_TABLE (ID integer primary key, DATA any);

insert into ANY_TABLE (ID, DATA) values (1, new SER_UDT());

select (C.DATA as SER_UDT).A from ANY_TABLE C where C.ID = 1;
</programlisting>

<example id="ex_serializebifs"><title>SERIALIZE/DESERIALIZE VSEs example</title>
<programlisting>
select (DESERIALIZE (SERIALIZE (new SER_UDT ())) as SER_UDT).A;
</programlisting>

<para>The SERIALIZE VSE can be used to store larger type instances into
LONG VARCHAR columns.  For example:</para>

<programlisting>
create table LOB_TABLE (ID integer primary key, LOB_DATA LONG VARCHAR);

insert into LOB_TABLE (ID, LOB_DATA) values (1, SERIALIZE (new SER_UDT()));

select (DESERIALIZE (BLOB_TO_STRING (LOB_DATA)) as SER_UDT).A
  from LOB_TABLE where ID = 1;
</programlisting>
</example>

<para>The serialization/deserialization for the non-SQL type instances is done
by the means of the hosted language (Java Object serialization API and CLR Binary
serialization API).  So to be serialized/deserialized correctly the Java classes
must implement the java.io.Serializable interface and the CLR classes should
have the [Serializable] attribute set.  For details refer to the respective
API documentation.</para>
</sect2>

<sect2 id="udtutilfuncs"><title>User Defined Types Utility Functions</title>

<para>Virtuoso implements the following user defined types utility functions:</para>

<simplelist>
  <member><link linkend="fn_udt_instance_of"><function>udt_instance_of()</function></link></member>
  <member><link linkend="fn_udt_defines_field"><function>udt_defines_field()</function></link></member>
  <member><link linkend="fn_udt_implements_method"><function>udt_implements_method()</function></link></member>
  <member><link linkend="fn_udt_get"><function>udt_get()</function></link></member>
  <member><link linkend="fn_udt_set"><function>udt_set()</function></link></member>
</simplelist>

</sect2>

<sect2 id="udthostedforiegnobjects"><title>Hosted Foreign Objects in Virtuoso</title>

<sect3 id="udtjvmhost"><title>Java VM Hosted Objects</title>

  <para>A special build of Virtuoso hosts a Java VM and allows manipulation of
  Java classes through the SQL user defined types.</para>

  <para>In order to access the Java class instances they have to be defined as Virtuoso
  types using CREATE TYPE and specifying LANGUAGE JAVA.  Java classes have to be
  in the CLASSPATH of the hosted Java VM.</para>

  <example id="ex_jvmhostobj"><title>Hosted Java Objects</title>

  <para>Java (Point.java):</para>

  <programlisting><![CDATA[
public class Point implements java.io.Serializable
{
  public double x = 0;
  public double y = 0;

  public Point (double new_x, double new_y)
  {
    x = new_x;
    y = new_y;
  }

  public double distance (Point p)
  {
    return Math.sqrt ((p.x - this.x) * (p.x - this.x) + (p.y - this.y) * (p.y - this.y));
  }
}
]]></programlisting>

  <para>This Java class should be compiled and the corresponding Point.class
  should be placed in the hosted VM's classpath.  Then a Virtuoso user defined
  type should be created as follows:</para>

<programlisting><![CDATA[
create type Point language java external name 'Point'
 as (
  x double precision external name 'x',
	y double precision external name 'y'
)

constructor method Point (new_x double precision, new_y double precision),
method distance (Point p) returns double precision external name 'distance';
]]></programlisting>

  <para>From now on the SQL Point type can be used to create instances of the
  Java Point class, access it's members, call it's methods and store it into
  tables (since the Java Point class implements the
  <computeroutput>java.io.Serializable</computeroutput> interface).</para>
  </example>

  <para>For the hosted Java objects a LANGUAGE JAVA should be specified.
  The format of EXTERNAL NAME is:</para>
  <simplelist>
    <member>the full name of the Java class for classes (ex. 'java.lang.Class')</member>
    <member>the name of the methods/instance members</member>
  </simplelist>

  <para>Since Java has static members and the Virtuoso SQL types do not,
  Virtuoso allows read-only access to static members through static observer
  functions with EXTERNAL VARIABLE NAME instead of EXTERNAL NAME.</para>

  <example id="ex_staticmembers"><title>Static Member Access</title>
  <programlisting><![CDATA[
java (stat.java) :
public class stat
{
  static stat_m double;
}
]]></programlisting>

  <para>Virtuoso SQL:</para>
  <programlisting><![CDATA[
create type stat language java external name 'stat'
static method observe_stat_m ()
  returns double precision external variable name 'stat_m';
]]></programlisting>
  </example>

  <para>Virtuoso does automatic mapping between the Virtuoso SQL data types
  and the Java data types.  Since Java data types are much more primitive than
  Virtuoso types it is safe to explicitly specify the Java type of an instance
  member, method parameter or method return value.  This is done by using the
  Type Signatures format described in the Java Native Interface Specification
  (chapter 3 : JNI Types and Data Structures : Table 3.2).  The signatures are
  supplied as string values to EXTERNAL TYPE clause.</para>

  <para>To facilitate the creation of the wrapper SQL types Virtuoso uses
  the Java Reflection API to get the description of the class in XML form.
  This XML is then transformed using an XSL stylesheet to makes the
  CREATE TYPE statements required automatically.  In the process it preserves
  the superclass/subclass relationships of the specified Java classes and
  represents them as a supertypes/subtypes in SQL.  The
  <link linkend="fn_jvm_ref_import"><function>jvm_ref_import()</function></link>
  procedure is used to create the XML by calling the Java Reflection API.</para>

  <para>The function <link linkend="fn_import_jar"><function>import_jar()</function></link>
  takes the same parameters as <function>jvm_ref_import()</function> but will
  automatically create and execute the create type statements within the Virtuoso
  server.</para>

  <table><title>Java Type to Virtuoso Type Conversions</title>
  <tgroup cols="2">
   <thead><row>
     <entry>Java Type/Class</entry>
     <entry>Virtuoso Internal Type</entry>
   </row></thead>
   <tbody>
     <row><entry>boolean</entry>
       <entry>smallint</entry></row>
     <row><entry>byte</entry>
       <entry>smallint</entry></row>
     <row><entry>char</entry>
       <entry>smallint</entry></row>
     <row><entry>short</entry>
       <entry>integer</entry></row>
     <row><entry>int</entry>
       <entry>integer</entry></row>
     <row><entry>long</entry>
       <entry>integer</entry></row>
     <row><entry>float</entry>
       <entry>real</entry></row>
     <row><entry>double</entry>
       <entry>double precision</entry></row>
     <row><entry>byte[]</entry>
       <entry>binary</entry></row>
     <row><entry>java.lang.String</entry>
       <entry>NVARCHAR</entry></row>
     <row><entry>java.util.Date</entry>
       <entry>DATETIME</entry></row>
     <row><entry>[]</entry>
       <entry>vector</entry></row>
   </tbody>
  </tgroup>
</table>

  <table><title>Virtuoso Type to Java Type Conversions</title>
  <tgroup cols="2">
   <thead><row>
     <entry>Virtuoso Internal Type</entry>
     <entry>Java Type/Class</entry>
   </row></thead>
   <tbody>
     <row><entry>smallint</entry>
       <entry>short</entry></row>
     <row><entry>integer</entry>
       <entry>integer</entry></row>
     <row><entry>real</entry>
       <entry>float</entry></row>
     <row><entry>double precision</entry>
       <entry>double</entry></row>
     <row><entry>varchar</entry>
       <entry>java.lang.String</entry></row>
     <row><entry>nvarchar</entry>
       <entry>java.lang.String</entry></row>
     <row><entry>datetime</entry>
       <entry>java.util.Date</entry></row>
     <row><entry>timestamp</entry>
       <entry>java.util.Date</entry></row>
     <row><entry>binary</entry>
       <entry>byte[]</entry></row>
   </tbody>
  </tgroup>
</table>

   <para>For all the other types encountered in the signatures of the Java
   methods/members it makes a forward reference to a Virtuoso/PL user defined
   type based on the java class name, replacing the dot ('.') with the
   underscore ('_') character.</para>

   <para>For example:</para>

    <para><computeroutput>'java.lang.System'</computeroutput>
	becomes <computeroutput>'java_lang_System'</computeroutput></para>

   <para>In order to correctly map a java superclass/subclass relationship between
   class A and class B when importing, it is necessary to include A, B and all
   the intermediate classes in the superclass/subclass chain in a single
   <function>import_jar()</function> call.</para>

  <para>To implement serialization/deserialization for Java object the Virtuoso
  needs the __virt_helper Java class.  This class contains utility functions
  implementing serialization/deserialization.  This class must be in the CLASSPATH.</para>

  <para>The Java VM hosted inside the Virtuoso binary is not started at startup,
  but when first needed.  It's startup is marked by a message in the Virtuoso
  log file.  An application can control the initialization of the Java VM by
  explicitly initializing the Java VM (preferably on server startup) by
  calling the VSE: <link linkend="fn_java_vm_attach"><function>java_vm_attach()</function></link></para>
  </sect3>


  <sect3 id="udtclrhosted"><title>CLR Hosted Objects</title>
  <para>A special virtuoso build is available to allow SQL types integration
  with the CLR (Common Language Runtime) on Windows.  This is achieved by
  providing COM server in C# (virtclr.dll) that is called from the native code
  through COM.</para>

  <para>The virtclr.dll library should be registered into the CLR's Global
  assembly cache.</para>

  <para>The semantics of CLR hosted objects are largely the same as those
  described for Java hosted objects.  As before, native objects need SQL Type
  wrappers, but with LANGUAGE CLR clause specified.</para>

  <para>To automatically create the SQL Type wrappers based on the CLR Reflection
  API the Virtuoso CLR binary has a system stored procedure:
  <link linkend="fn_import_clr"><function>import_clr()</function></link></para>

  <para>There are three forms for specifying the EXTERNAL NAME of a CLR class:</para>

  <itemizedlist>
   <listitem>a) <computeroutput>&lt;Assembly public name&gt;/&lt;namespace-prefixed-class-name&gt;</computeroutput>
   Here the Virtuoso CLR host issues Assembly.Load with <computeroutput>&lt;Assembly public
   name&gt;</computeroutput> to find the assembly.  After finding it, it looks
   for <computeroutput>&lt;namespace-prefixed-class-name&gt;</computeroutput> in it.</listitem>
   <listitem>b) <computeroutput>&lt;namespace-prefixed-class-name&gt;</computeroutput>
   Here the Virtuoso CLR host issues Assembly.Load with
   <computeroutput>&lt;namespace-prefixed-class-name&gt;</computeroutput>.  After
   finding it, it looks for <computeroutput>&lt;namespace-prefixed-class-name&gt;</computeroutput>
   in it.</listitem>
   <listitem>c) <computeroutput>&lt;path-to-the-assembly-binary&gt;/&lt;namespace-prefixed-class-name&gt;</computeroutput>
   Here the Virtuoso CLR host issues Assembly.LoadFrom with <computeroutput>&lt;path-to-the-assembly-binary&gt;</computeroutput>.
   After finding it, it looks for <computeroutput>&lt;namespace-prefixed-class-name&gt;</computeroutput>
   in it.</listitem>
  </itemizedlist>

  <para>
  The Virtuoso CLR host does the above when creating an instance of the type,
  accessing static methods or properties.</para>

  <para>However when it deserializes an serialized CLR instance it calls the
  CLR deserialization class BinaryFormatter.  The BinaryFormatter.Deserialize
  calls internally Assembly.Load to find the serialized class description.
  So although the classes defined with EXTERNAL name as in c) above are otherwise
  accessible (and serializable) they will possibly not deserialize correctly
  (as the assembly binary may not be findable through the Assembly.Load).  To
  avoid that CLR limitation it is advisable to use the EXTERNAL NAME forms
  a) and b) wherever possible.</para>

  <para>The Assembly.Load process of finding Assemblies is very well documented
  on the <ulink url="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconhowruntimelocatesassemblies.asp">MSDN</ulink>.
  Note that if an assembly was loaded through Assembly.LoadFrom it is not
  considered as "already loaded" by the Assembly.Load.  The Virtuoso CLR is a
  CLR runtime host.  As such it can use the normal CLR configuration files. It also
  is able of using private assemblies.</para>

  <tip><title>See Also:</title>
    <para>The <link linkend="createassembly">Create Assembly</link> Syntax</para></tip>

  </sect3>

  <sect3 id="udtaspxhosting"><title>ASPX Hosting Using the Hosted CLR</title>
  <para>Virtuoso CLR hosting allows ASPX pages to be executed through the
  Virtuoso HTTP server inside the hosted CLR Virtual machine.  To enable this
  support an additional library  (virt_http.dll) needs to be registered with
  the Global Assembly cache.  Having achieve this and copying ASPX project files
  under the Virtuoso HTTP server's root allows direct execution of the ASPX
  page.  See the sample ASPX pages in the Virtuoso distribution.</para>

  <para>If the ASPX project files reside in a WebDAV directory they are copied
  into a temporary file system directory under a special temporary directory
  (configurable by the TempASPXDir INI parameter in [HTTPServer] section of
  <link linkend="VIRTINI">virtuoso ini</link> file) before executed.  In order
  to be execute correctly from WebDAV the ASPX files should have Execute WebDAV
  permission set them.  The execution of ASPX is also controlled by the
  EnableDavVSP INI parameter in the [HTTPServer] as with any active content
  within WebDAV.</para>

  <tip><title>See Also:</title>
    <para><link linkend="rthwritaspxapps">Deploying ASP.Net Web Applications</link></para>
	<para><link linkend="runtimehosting">Runtime Hosting</link></para></tip>
  </sect3>

  <sect3 id="udtaspxhostexprsdeps"><title>Expressing Hosted Language Supertype/Subtype Dependencies With Virtuoso/PL User-Defined-Types</title>

   <para>It is also possible to represent the tree or in-part of Java or the CLR's
   superclass/subclass hierarchy with Virtuoso user defined type mappings.</para>

   <para>Consider the following sample Java code:</para>

<programlisting><![CDATA[
class g1 { public int g1_value; public int mtd_g1 (int x) { return g1_value; } };
class g2 extends g1 { public int g2_value; public int mtd_g2 (int x) { return g2_value; } };
class g3 extends g2 { public int g3_value; };
class g2_sib extends g1 { public int g2_sib_value; };

class uses_types {
  public static g3 mtd (int x) { return new g3 (); }
}
]]></programlisting>


   <para>One can create SQL user defined types for
   <computeroutput>g1</computeroutput>, <computeroutput>g2</computeroutput>
   and <computeroutput>g3</computeroutput> to represent the
   <computeroutput>g1</computeroutput>/<computeroutput>g2</computeroutput>/
   <computeroutput>g3</computeroutput> Java class hierarchy if calling
   <computeroutput>mtd_g1</computeroutput> and
   <computeroutput>mtd_g2</computeroutput> is needed:</para>

<programlisting><![CDATA[
create type sql_g1 language java external name 'g1' as (
    g1_value int)
method mtd_g1 (x integer) returns integer;

create type sql_g2 under sql_g1 language java external name 'g2' as (
    g2_value int)
method mtd_g2 (x integer) returns integer;

create type sql_g3 under sql_g2 language java external name 'g3' as (
    g3_value int)
method mtd_g3 (x integer) returns integer;

create type uses_types language java external name 'uses_types'
 static method mtd (x integer) returns sql_g3;
]]></programlisting>

   <para>provided with the above, one can call
   <computeroutput>uses_types.g3 ()</computeroutput>method and
   call <computeroutput>mtd_g1 ()</computeroutput> on the returned instance in
   Virtuoso/PL as follows:</para>

<programlisting><![CDATA[
select uses_types::mtd (12).mtd_g1 (10);
]]></programlisting>

   <para>Sometimes it is not desirable or necessary to mirror the full
   supertype/subtype hierarchy from Java to Virtuoso/PL.</para>

   <para>For the above example only <computeroutput>sql_g2</computeroutput>
   and <computeroutput>sql_g3</computeroutput> can be defined if the goal was
   to call <computeroutput>mtd_g2()</computeroutput> instead of
   <computeroutput>mtd_g1()</computeroutput>.</para>

   <para>When creating instances of the Virtuoso/PL user defined types to
   represent the data returned by the hosted code, Virtuoso tries to find the
   closest common ancestor of the hosted instance's class and the ones defined
   in Virtuoso as user defined types.</para>

   <para>For example if in the above example a Java function returns an instance of
   <computeroutput>g3</computeroutput> and there is a
   <computeroutput>sql_g3</computeroutput> defined inside virtuoso the
   <computeroutput>g3</computeroutput> Java instance will be wrapped into an
   <computeroutput>sql_g3</computeroutput> Virtuoso/PL instance.  Note that
   that will not depend on the presence or absence of
   <computeroutput>sql_g1</computeroutput> and
   <computeroutput>sql_g2</computeroutput> definitions - i.e. Virtuoso will favor
   the exact match.</para>

   <para>If, however <computeroutput>sql_g3</computeroutput> is not defined, but
   <computeroutput>sql_g2</computeroutput> and <computeroutput>sql_g1</computeroutput>
   are, then the <computeroutput>g3</computeroutput> instance will be wrapped
   up in an <computeroutput>sql_g2</computeroutput> instance when returned.</para>

   <para>Similarly, if an instance of the <computeroutput>g2_sib</computeroutput>
   is to be returned in Virtuoso/PL and <computeroutput>sql_g1</computeroutput>
   to <computeroutput>sql_g3</computeroutput> are defined, Virtuoso will wrap the
   <computeroutput>g2_sib</computeroutput> Java instance into an
   <computeroutput>sql_g1</computeroutput> SQL instance.</para>

   </sect3>
</sect2>

<sect2 id="udtrepressentsoapstruct">
 <title>Using User Defined Types to Represent SOAP Structures</title>

 <para>The Virtuoso SOAP server is capable of using user defined types (both
 native and hosted) to represent structures in SOAP requests/responses.
 Normally a SOAP exposed procedure would have references to defined schema
 types (__SOAP_TYPE for it's return type and for it's argument types).  When
 such a schema type represents a structure (see the SOAP RPC encoding) the
 Virtuoso SOAP server will map the structure to an array of name/value pairs
 for it's members (the type of value returned by the soap_box_structure VSE).
 The user defined types however are better suited for representing such data.
 In order for a user defined type to be usable in SOAP, it must have a default
 constructor (no arguments).  For native types that is always true (since they
 have the implicit constructor setting up the member's values to the respective
 DEFAULT values from the user defined type declaration).  The Virtuoso SOAP
 implementation supports two ways of specifying how a SOAP value XML fragment
 should be materialized as a user defined type instance, as follows.</para>

 <sect3 id="udtsoapuseschemafrag"><title>Using Schema Fragments</title>
  <para>The <link linkend="fn_soap_dt_define"><function>SOAP_DT_DEFINE()</function></link>
  function is used to map a particular schema fragment describing a composite
  schema type for SOAP usage.  This now takes an additional optional argument to
  establish a link to a user defined type name:</para>

  <programlisting><![CDATA[
create type SO_S_30
  as (
      "varString" nvarchar,
      "varInt" integer,
      "varFloat" real,
      "processingResult" nvarchar,
      "vmVersion" nvarchar)
  constructor method SO_S_30 (),
  method process_data () returns nvarchar;

soap_dt_define ('',
'<complexType name="SOAPStruct"
   xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   xmlns="http://www.w3.org/2001/XMLSchema"
   targetNamespace="services.wsdl"
   xmlns:tns="services.wsdl">
  <all>
    <element name="varString" type="string" nillable="true"/>
    <element name="varInt" type="int" nillable="true"/>
    <element name="varFloat" type="float" nillable="true"/>
    <element name="processingResult" type="string" nillable="true"/>
    <element name="vmVersion" type="string" nillable="true"/>
  </all>
</complexType>', 'SO_S_30');
]]></programlisting>
  <para>The CREATE TYPE statement defines the user defined type SO_S_30 as
  having 5 data members, a no-parameters constructor and a processing method.
  The <function>soap_dt_define()</function> call maps the SO_S_30 to a schema
  type SOAPStruct which also has 5 data members and makes that schema type
  available to SOAP.  Now we create a SOAP exposed stored procedure:</para>

  <programlisting><![CDATA[
create procedure echoSOAPStructSch (
    in sst SO_S_30 __soap_type 'services.wsdl:SOAPStruct')
returns SO_S_30 __soap_type 'services.wsdl:SOAPStruct'
{
  declare processingResult nvarchar;
  processingResult := sst.process_data ();
  return sst;
};
]]></programlisting>
  <para>When processing the SOAP request for calling that stored procedure,
  the SOAP server will call the default constructor for SO_S_30 (require to
  create the empty instance) and will fill up the values from the incoming XML
  fragment for the sst parameter to the members of the newly created SO_S_30
  instance.  Then it will pass that instance as a value for the sst parameter
  of the echoSOAPStructSch function.  As a result echoSOAPStructSch will correctly
  execute the member function process_data.  Then it will return the (possibly)
  modified SO_S_30 instance to the SOAP server.  The SOAP server will make the
  XML fragment for the return value based on the SOAPStruct schema fragment using
  the values from the SO_S_30 members.</para>

  <para>This approach allows easy migration for the existing SOAP services
  using structures.  To upgrade a SOAP service procedure to use user defined
  types one should define the types and add the additional argument to
  <function>SOAP_DT_DEFINE()</function>.</para>

  <para>For developing new SOAP services, however, it is redundant to create the
  schema fragment in addition to creating the user defined type to hold the
  SOAP structure.</para>

  <para>For this reason, Virtuoso offers a second approach in using user
  defined types in SOAP.</para>
 </sect3>

 <sect3 id="udtsoapudt"><title>Using the User Defined Type Definition</title>

  <para>Consider the altered definition of SO_S_30 as follows:</para>

  <programlisting><![CDATA[
create type SO_S_30
  as (
      varString nvarchar __soap_type 'string' __soap_name 'varString',
      "varInt" integer __soap_type 'int',
      "varFloat" real __soap_type 'float',
      "processingResult" nvarchar __soap_type 'string',
      "vmVersion" nvarchar)
  __soap_type 'services.wsdl:SOAPStruct'
  constructor method SO_S_30 (),
  method process_data () returns nvarchar;
]]></programlisting>

   <para>and the procedure echoSOAPStructSch as:</para>

   <programlisting><![CDATA[
create procedure echoSOAPStructSch (in sst SO_S_30) returns SO_S_30
{
  declare processingResult nvarchar;
  processingResult := sst.process_data ();
  return sst;
};
]]></programlisting>

   <para>Now all we have to do is expose the echoSOAPStructSch in a SOAP service.
   The SOAP server will take into account the fact that the sst type and the
   return type are user defined types and automatically make the WSDL
   description (including the schema fragments) and will correctly process
   the incoming XML.</para>

   <para>The SOAP names and data type names inside the user defined type definition
   are optional and default to the SQL member's name for names and employ
   a straight mapping of the PL types to the SOAP types for data types.</para>

 </sect3>
</sect2>

<sect2 id="udtcnsmsoap"><title>Consuming Third-Party SOAP Services via User Defined Types</title>

<para>Virtuoso provides function for acting as a SOAP client called
<link linend="fn_soap_client"><function>SOAP_CLIENT()</function></link>.
Embedding SOAP Web Service methods in Virtuoso/PL procedures using this function,
however, is not suitable in most cases, especially if the services contained a
large number of parameters of different type, the procedure could become very
complex, the encoding may also vary.  Thus direct SOAP_CLIENT() invocation in
some cases in non-trivial and may lead to errors that are hard to debug.</para>

<para>To aid development of Web based applications written in PL that use
the SOAP protocol, Virtuoso introduces two new approaches for consuming
a Web service:</para>

<simplelist>
  <member>generate SOAP proxy wrappers encapsulated in a PL Module</member>
  <member>generate a User Defined Type (UDT) for SOAP proxy encapsulation.</member>
</simplelist>

<para>Please note that both methods of making a SOAP proxy-wrapper requires
a WSDL description.  If some SOAP service does not have a corresponding
WSDL, neither of these methods can be used.</para>

<para>The first approach can be achieved using the SOAP_WSDL_IMPORT() function.
This will make a PL module utilizing the SOAP_CLIENT() function that will import the
complex types and pass appropriate parameters.  But it has one significant
problem in that it will return the result as a parsed XML entity. The result should
then be processed in the application code, which requires prior knowledge of
the return parameters.</para>

<para>The second approach consists of creating a UDT encapsulation of
the SOAP wrappers using the
<link linkend="fn_wsdl_import_udt"><function>WSDL_IMPORT_UDT()</function>.</link></para>

<tip><title>See Also</title>
<para>The <link linkend="fn_soap_wsdl_import"><function>SOAP_WSDL_IMPORT()</function></link> function.</para>
<para>The <link linkend="fn_wsdl_import_udt"><function>WSDL_IMPORT_UDT()</function></link> function.</para>
</tip>

<para>The import function <function>WSDL_IMPORT_UDT()</function> has two
phases:</para>

 <simplelist>
  <member>retrieve and expand the WSDL file (expansion will be done if import is specified)</member>
  <member>compile the result and make SQL script with UDT definition</member>
 </simplelist>

<para>The following points will hold true for this method of SOAP encapsulation:</para>

<itemizedlist>
  <listitem>Any XML Schema types, required for calling the target SOAP service will be imported in database.</listitem>
  <listitem>A UDT will be created for each service defined within the WSDL description. </listitem>
  <listitem>The UDT will have members: url, request, response, and debug.
   <itemizedlist>
    <listitem>the 'url' member designate the endpoint for SOAP invocation</listitem>
    <listitem>debug is a flag to manage wrappers to return wire dumps if needed</listitem>
    <listitem>request and response members will contain wire dumps  if 'debug' is equal to 'true' (integer 1).</listitem>
    </itemizedlist></listitem>
  <listitem>for each method defined in the WSDL description there will be UDT's method.</listitem>
  <listitem>each method of UDT will contain:
   <itemizedlist>
    <listitem>a number IN/OUT/INOUT parameters (depending on the target method)</listitem>
    <listitem>no return value, SOAP does not define explicitly return values.</listitem>
    <listitem>call to the SOAP_CLIENT () function with appropriate arguments</listitem>
    <listitem>XPATH over the result and transform with SOAP validation functions to
      ensure value of OUT and INOUT parameters.  </listitem>
   </itemizedlist>
  </listitem>
 </itemizedlist>

 <tip><title>See Also</title>
 <para>The Virtuoso Administration Interface provides a web based
 interface for importing WSDL definitions and creating UDTs and procedures.
 This can be found in the <link linkend="admiui.wsdl">Visual Server Administration
 Interface</link> Chapter.</para>
 </tip>
 </sect2>

 <sect2 id="udtsecurity"><title>UDT Security</title>

  <para>Security of UDTs is maintained through normal SQL GRANT and REVOKE
  statements via a simple extension.  You can define the level of access to both native
  and externally hosted UDTs.</para>

  <para>Grants for persistent user defined types are persisted into the SYS_GRANTS
  table.  Grants on temporary user defined types are in-memory only and are lost
  (together with the temporary user defined type definition) when the server is
  restarted.</para>

  <para>There are two GRANT/REVOKE types for UDTs as follows:</para>

  <simplelist>
    <member><emphasis>EXECUTE</emphasis> - all methods and members of a class are accessible to the grantee.</member>
    <member><emphasis>UNDER</emphasis> - the grantee can create subclasses of the class.</member>
  </simplelist>

<programlisting><![CDATA[
GRANT/REVOKE EXECUTE on <user_defined_type>
GRANT/REVOKE UNDER on <user_defined_type>
]]></programlisting>

  <note><title>Note:</title>
    <para>SQL modules, user defined types and SQL stored procedures are exposed
	to GRANT/REVOKE in the same namespace, therefore care must be taken avoid
	inadvertently granting to multiple objects at the same time.</para></note>

 </sect2>
</sect1>