mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-40394 XML schema fails on self-referencing type.
A schema type that refers to itself, directly or through other types or groups, was validated with a single shared compositor state per type. A nested use of the type reset the state of the outer one, so XMLISVALID() gave wrong results for recursive schemas. Now every recursion level of an XMLSchema_user_type gets its own copy of the type's content (get_copy()/copy_tags()). Copies are kept on a per-type stack while validating, and released copies are put in m_c_free and reused, so memory doesn't grow with each validated row. reset_types() unwinds any state left by a validation that aborted. Other changes: - XMLSchema_item::is_validate_done() is replaced with ::end_validation(st). It is no longer a pure check: it pops the compositor stack and must be paired with validate_prepare(). - validate_prepare() can now fail, and the failure is propagated. - A recursion depth limit (MAX_RECURSION_DEPTH, 1024) is added, counted per type. When it is hit, or on OOM during validation, XMLISVALID() returns errors/warnings. - XMLSchema_group_def now derives from XMLSchema_user_type, so groups get the same copy mechanism. As a side effect <xs:group final=...> is accepted. - XMLSchema_group_reference now counts occurrences, so minOccurs and maxOccurs of a group reference are enforced. - XMLSchema_group_def::check_type() checks for circular groups, and XMLSchema_attribute::check_type() is removed (named types and groups are checked globally). - The circular-reference error names the construct: "complexType B has bad circular references" instead of "type B has ...". The affected .result lines are re-recorded. - Hook chains (m_next_tag) are replaced with List<> because tags are now copied.
This commit is contained in:
committed by
Alexey Botchkov
parent
8fd3cfef2a
commit
a601069172
File diff suppressed because it is too large
Load Diff
@@ -442,7 +442,7 @@ XMLISVALID(@xml, @schema)
|
||||
set @xml= '<payment> </payment>';
|
||||
select XMLISVALID(@xml, @schema);
|
||||
XMLISVALID(@xml, @schema)
|
||||
0
|
||||
1
|
||||
set @schema= '<?xml version="1.0"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
@@ -513,7 +513,7 @@ XMLISVALID(@xml, @schema)
|
||||
set @xml= '<payment> </payment>';
|
||||
select XMLISVALID(@xml, @schema);
|
||||
XMLISVALID(@xml, @schema)
|
||||
0
|
||||
1
|
||||
set @schema= '<?xml version="1.0"?>
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
@@ -630,7 +630,7 @@ set @xml= '
|
||||
<ProductData> </ProductData>';
|
||||
select XMLISVALID(@xml, @schema);
|
||||
XMLISVALID(@xml, @schema)
|
||||
0
|
||||
1
|
||||
|
||||
<attribute>
|
||||
|
||||
@@ -1027,8 +1027,8 @@ set @xml= '
|
||||
<!-- Group Elements End -->
|
||||
<OrderDate>2026-06-01</OrderDate>
|
||||
</RegularOrder>';
|
||||
select XMLISVALID(@xml, @schema);
|
||||
XMLISVALID(@xml, @schema)
|
||||
select XMLISVALID(@xml, @schema) Ex0;
|
||||
Ex0
|
||||
0
|
||||
set @schema= ' <?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
@@ -1075,8 +1075,8 @@ set @xml= '
|
||||
<!-- Group Elements End -->
|
||||
<OrderDate>2026-06-01</OrderDate>
|
||||
</RegularOrder>';
|
||||
select XMLISVALID(@xml, @schema);
|
||||
XMLISVALID(@xml, @schema)
|
||||
select XMLISVALID(@xml, @schema) Ex1;
|
||||
Ex1
|
||||
1
|
||||
set @schema= ' <?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
@@ -1121,8 +1121,8 @@ set @xml= '
|
||||
<!-- Group Elements End -->
|
||||
<OrderDate>2026-06-01</OrderDate>
|
||||
</RegularOrder>';
|
||||
select XMLISVALID(@xml, @schema);
|
||||
XMLISVALID(@xml, @schema)
|
||||
select XMLISVALID(@xml, @schema) Ex1;
|
||||
Ex1
|
||||
1
|
||||
set @schema= ' <?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
@@ -2095,7 +2095,7 @@ SELECT XMLISVALID('<root>x</root>',
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="root" type="A"/></xs:schema>') AS r;
|
||||
ERROR HY000: Invalid XML schema, type B has bad circular references.
|
||||
ERROR HY000: Invalid XML schema, complexType B has bad circular references.
|
||||
SELECT XMLISVALID('<root>x</root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="A">
|
||||
@@ -2110,7 +2110,7 @@ SELECT XMLISVALID('<root>x</root>',
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="root" type="A"/></xs:schema>') AS r;
|
||||
ERROR HY000: Invalid XML schema, type B has bad circular references.
|
||||
ERROR HY000: Invalid XML schema, complexType B has bad circular references.
|
||||
SELECT XMLISVALID( '<root>x</root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="root" type="A"/>
|
||||
@@ -2118,4 +2118,694 @@ SELECT XMLISVALID( '<root>x</root>',
|
||||
<xs:restriction base="A"/>
|
||||
</xs:simpleType>
|
||||
</xs:schema>' ) AS r;
|
||||
ERROR HY000: Invalid XML schema, type A has bad circular references.
|
||||
ERROR HY000: Invalid XML schema, simpleType A has bad circular references.
|
||||
|
||||
MDEV-40394 XML schema fails on self-referencing type.
|
||||
|
||||
SELECT XMLISVALID('
|
||||
<root>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> One </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<leaf> Two </leaf>
|
||||
</lt>
|
||||
<rt>
|
||||
<leaf> Three </leaf>
|
||||
</rt>
|
||||
</rt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> Four </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
</lt>
|
||||
</rt>
|
||||
</root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:all>
|
||||
<xs:element name="lt" type="T" minOccurs="0"/>
|
||||
<xs:element name="rt" type="T" minOccurs="0"/>
|
||||
<xs:element name="leaf" type="xs:string" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as V;
|
||||
V
|
||||
1
|
||||
SELECT XMLISVALID('
|
||||
<root>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> One </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<leaf> Two </leaf>
|
||||
</lt>
|
||||
<rt>
|
||||
<leaf> Three </leaf>
|
||||
</rt>
|
||||
</rt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> Four </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
</lt>
|
||||
</rt>
|
||||
</root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:element name="lt" type="T" minOccurs="0"/>
|
||||
<xs:element name="rt" type="T" minOccurs="0"/>
|
||||
<xs:element name="leaf" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as Expect_1;
|
||||
Expect_1
|
||||
1
|
||||
SELECT XMLISVALID('<root><child/></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence><xs:element name="child" type="T"/></xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as V;
|
||||
V
|
||||
0
|
||||
SELECT XMLISVALID('<root><child> <child/> <child/></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence><xs:element name="child" type="T"/></xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as V;
|
||||
V
|
||||
0
|
||||
SELECT XMLISVALID('<root><child> <child> <child> <child/> </child></child></child></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence minOccurs="0">
|
||||
<xs:element name="child" type="T"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as V;
|
||||
V
|
||||
1
|
||||
SELECT XMLISVALID('<root><x> a </x> </root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:group name="G">
|
||||
<xs:sequence>
|
||||
<xs:element name="x" type="xs:string"/>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence>
|
||||
</xs:group>
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') AS v;
|
||||
ERROR HY000: Invalid XML schema, group G has bad circular references.
|
||||
SELECT XMLISVALID('<root><x> a </x> </root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:group name="G">
|
||||
<xs:sequence>
|
||||
<xs:element name="x" type="xs:string"/>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence>
|
||||
</xs:group>
|
||||
<xs:element name="root">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
</xs:schema>') AS v;
|
||||
ERROR HY000: Invalid XML schema, group G has bad circular references.
|
||||
SELECT XMLISVALID('<root><self><x>i</x></self><x>o</x></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T"><xs:all>
|
||||
<xs:element name="x" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="self" type="T" minOccurs="0"/>
|
||||
</xs:all></xs:complexType>
|
||||
<xs:element name="root" type="T"/></xs:schema>') as A_expect_1;
|
||||
A_expect_1
|
||||
1
|
||||
SELECT XMLISVALID('<root><self><x>i1</x><x>i2</x></self><x>o1</x><x>o2</x></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:element name="self" type="T" minOccurs="0"/>
|
||||
<xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="2"/>
|
||||
</xs:sequence></xs:complexType>
|
||||
<xs:element name="root" type="T"/></xs:schema>') as B_expect_1;
|
||||
B_expect_1
|
||||
1
|
||||
SELECT XMLISVALID('<root><x>a</x><self></self><x>b</x></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T"><xs:all>
|
||||
<xs:element name="x" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="self" type="T" minOccurs="0"/>
|
||||
</xs:all></xs:complexType>
|
||||
<xs:element name="root" type="T"/></xs:schema>') as C_expect_0;
|
||||
C_expect_0
|
||||
0
|
||||
SELECT XMLISVALID('
|
||||
<root>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> One </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<leaf> Two </leaf>
|
||||
</lt>
|
||||
<rt>
|
||||
<leaf> Three </leaf>
|
||||
</rt>
|
||||
</rt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<BAD_leaf> Four </BAD_leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
</lt>
|
||||
</rt>
|
||||
</root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:element name="lt" type="T" minOccurs="0"/>
|
||||
<xs:element name="rt" type="T" minOccurs="0"/>
|
||||
<xs:element name="leaf" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as Expect_0;
|
||||
Expect_0
|
||||
0
|
||||
#
|
||||
# Recursion through a shared xs:group
|
||||
# Every group_reference shares the group's single compositor, so a
|
||||
# nested use of the group resets the state of the outer one.
|
||||
#
|
||||
SET @schema_group= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:group name="G">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="T2" minOccurs="0"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:group>
|
||||
<xs:complexType name="T1"><xs:sequence><xs:group ref="G"/></xs:sequence></xs:complexType>
|
||||
<xs:complexType name="T2"><xs:sequence><xs:group ref="G"/></xs:sequence></xs:complexType>
|
||||
<xs:element name="root" type="T1"/>
|
||||
</xs:schema>';
|
||||
SET @schema_seq= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T1">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="T2" minOccurs="0"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="T2">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="T2" minOccurs="0"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T1"/>
|
||||
</xs:schema>';
|
||||
# Valid: nested <a> holds its own <b>, outer <b> follows. Expect 1
|
||||
# (same structure without the group, for comparison, is also 1)
|
||||
SELECT XMLISVALID('<root><a><b>x</b></a><b>y</b></root>', @schema_group) AS group_valid,
|
||||
XMLISVALID('<root><a><b>x</b></a><b>y</b></root>', @schema_seq) AS seq_valid;
|
||||
group_valid seq_valid
|
||||
1 1
|
||||
# Valid, two levels deep. Expect 1 / 1
|
||||
SELECT XMLISVALID('<root><a><a><b>x</b></a><b>y</b></a><b>z</b></root>', @schema_group) AS group_valid,
|
||||
XMLISVALID('<root><a><a><b>x</b></a><b>y</b></a><b>z</b></root>', @schema_seq) AS seq_valid;
|
||||
group_valid seq_valid
|
||||
1 1
|
||||
# Invalid: outer <b> missing. Expect 0 / 0
|
||||
SELECT XMLISVALID('<root><a><b>x</b></a></root>', @schema_group) AS group_invalid,
|
||||
XMLISVALID('<root><a><b>x</b></a></root>', @schema_seq) AS seq_invalid;
|
||||
group_invalid seq_invalid
|
||||
0 0
|
||||
# Invalid: inner <b> missing. Expect 0 / 0
|
||||
SELECT XMLISVALID('<root><a></a><b>y</b></root>', @schema_group) AS group_invalid,
|
||||
XMLISVALID('<root><a></a><b>y</b></root>', @schema_seq) AS seq_invalid;
|
||||
group_invalid seq_invalid
|
||||
0 0
|
||||
#
|
||||
# xs:group reference occurrence counting.
|
||||
# minOccurs/maxOccurs on a group reference, including an emptiable group.
|
||||
#
|
||||
SET @pre= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">';
|
||||
SET @post= '<xs:element name="c" type="xs:string"/></xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Group with required content, minOccurs=2 maxOccurs=2
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G" minOccurs="2" maxOccurs="2"/>', @post);
|
||||
# One occurrence: too few. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
0
|
||||
# Two occurrences. Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><a>2</a><b>2</b><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Three occurrences: too many. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><a>2</a><b>2</b><a>3</a><b>3</b><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
0
|
||||
# Second occurrence incomplete. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><a>2</a><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
0
|
||||
# Group with minOccurs=0
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G" minOccurs="0"/>', @post);
|
||||
# Group absent. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Group present. Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Group present twice (maxOccurs defaults to 1). Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><a>2</a><b>2</b><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
0
|
||||
# Group present but incomplete. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
0
|
||||
# Group with minOccurs=1 maxOccurs=unbounded
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G" maxOccurs="unbounded"/>', @post);
|
||||
# Absent: too few. Expect 0
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
0
|
||||
# Four occurrences. Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><b/><a/><b/><a/><b/><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Emptiable group (all particles optional), default minOccurs=1
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G"/>', @post);
|
||||
# Group content absent. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Group content present. Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Emptiable group, minOccurs=2 maxOccurs=3
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G" minOccurs="2" maxOccurs="3"/>', @post);
|
||||
# Group content absent. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Three <a>. Expect 1
|
||||
SELECT XMLISVALID('<root><a/><a/><a/><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Four <a>: too many. Expect 0
|
||||
SELECT XMLISVALID('<root><a/><a/><a/><a/><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
0
|
||||
# Emptiable group reference as the last particle of a sequence
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence></xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>');
|
||||
# Group content absent, no tag reaches the group reference. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Group content present. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c><a>1</a></root>', @schema_group) AS grp;
|
||||
grp
|
||||
1
|
||||
# Required <c> missing. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a></root>', @schema_group) AS grp;
|
||||
grp
|
||||
0
|
||||
#
|
||||
# recursion depth limit and recovery after aborted validation
|
||||
#
|
||||
SET @schema_rec= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:all>
|
||||
<xs:element name="c" type="T" minOccurs="0"/>
|
||||
<xs:element name="leaf" type="xs:string" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Just below the depth limit. Expect 1
|
||||
SELECT XMLISVALID(CONCAT('<root>', REPEAT('<c>', 1021), '<leaf>x</leaf>',
|
||||
REPEAT('</c>', 1021), '</root>'), @schema_rec) AS below_limit;
|
||||
below_limit
|
||||
1
|
||||
SELECT XMLISVALID(CONCAT('<root>', REPEAT('<c>', 1100), '<leaf>x</leaf>',
|
||||
REPEAT('</c>', 1100), '</root>'), @schema_rec) AS over_limit;
|
||||
ERROR HY000: The recursive depth limit for XML validation was overrun.
|
||||
# Rows after an aborted validation are not affected by it
|
||||
CREATE TABLE t1 (id INT, x LONGTEXT);
|
||||
INSERT INTO t1 VALUES
|
||||
(1, '<root><c><c><d/></c></c></root>'),
|
||||
(2, '<root><c><c><leaf>x</leaf></c></c></root>'),
|
||||
(3, '<root><c><c_bad><leaf>x</leaf></c></c></root>'),
|
||||
(4, '<root><c><c><leaf>x</leaf></c></c></root>'),
|
||||
(5, '<root><c><c><d/></c></c></root>'),
|
||||
(6, '<root><c><leaf>x</leaf></c></root>');
|
||||
SELECT id, XMLISVALID(x, @schema_rec) AS r FROM t1 ORDER BY id;
|
||||
id r
|
||||
1 0
|
||||
2 1
|
||||
3 0
|
||||
4 1
|
||||
5 0
|
||||
6 1
|
||||
DROP TABLE t1;
|
||||
# Recursion through xs:choice
|
||||
SET @schema_rec= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:choice>
|
||||
<xs:element name="c" type="T"/>
|
||||
<xs:element name="leaf" type="xs:string"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><c><c><leaf>a</leaf></c></c></root>', @schema_rec) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 0
|
||||
SELECT XMLISVALID('<root><c><c><leaf>a</leaf><leaf>b</leaf></c></c></root>', @schema_rec) AS r;
|
||||
r
|
||||
0
|
||||
# Expect 0
|
||||
SELECT XMLISVALID('<root><c><c><d/></c></c></root>', @schema_rec) AS r;
|
||||
r
|
||||
0
|
||||
# Recursion through an anonymous type
|
||||
SET @schema_rec= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence><xs:element name="b" type="T" minOccurs="0"/></xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="leaf" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a><b><a><b><leaf>x</leaf></b></a><leaf>y</leaf></b></a><leaf>z</leaf></root>', @schema_rec) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 0
|
||||
SELECT XMLISVALID('<root><a><b><a><b><leaf>x</leaf></b></a></b></a><leaf>z</leaf></root>', @schema_rec) AS r;
|
||||
r
|
||||
0
|
||||
# Choice with an unfinished nested compositor
|
||||
SET @schema_choice= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:choice>
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b></root>', @schema_choice) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><c>1</c></root>', @schema_choice) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 0, the chosen sequence misses <b>
|
||||
SELECT XMLISVALID('<root><a>1</a></root>', @schema_choice) AS r;
|
||||
r
|
||||
0
|
||||
# The same, with the choice nested in a sequence
|
||||
SET @schema_choice= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:choice>
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:choice>
|
||||
<xs:element name="d" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b><d>3</d></root>', @schema_choice) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a></root>', @schema_choice) AS r;
|
||||
r
|
||||
0
|
||||
# Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><d>3</d></root>', @schema_choice) AS r;
|
||||
r
|
||||
0
|
||||
# Choice alternative is a group holding an incomplete sequence
|
||||
SET @schema_choice= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:group name="G">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:group>
|
||||
<xs:complexType name="T">
|
||||
<xs:choice>
|
||||
<xs:group ref="G"/>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b></root>', @schema_choice) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a></root>', @schema_choice) AS r;
|
||||
r
|
||||
0
|
||||
# Choice with maxOccurs>1: an alternative that was tried but not chosen
|
||||
# must not leave stale state, so the repeated alternative is accepted
|
||||
SET @schema_choice= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:choice maxOccurs="3">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b><c>3</c></root>', @schema_choice) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><c>1</c><a>2</a><b>3</b></root>', @schema_choice) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><c>1</c><c>2</c></root>', @schema_choice) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><c>1</c><c>2</c><c>3</c></root>', @schema_choice) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b><a>3</a><b>4</b></root>', @schema_choice) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 0, incomplete sequence alternative
|
||||
SELECT XMLISVALID('<root><c>1</c><a>2</a></root>', @schema_choice) AS r;
|
||||
r
|
||||
0
|
||||
# Expect 0, four occurrences
|
||||
SELECT XMLISVALID('<root><c>1</c><c>2</c><c>3</c><c>4</c></root>', @schema_choice) AS r;
|
||||
r
|
||||
0
|
||||
#
|
||||
# An unbounded nested xs:sequence followed by another element
|
||||
# (existing bug in XMLSchema_sequence::validate_tag_name: the nested
|
||||
# sequence takes the tag that belongs to the following element).
|
||||
#
|
||||
SET @schema_nested= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:sequence maxOccurs="unbounded">
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><c/></root>', @schema_nested) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><b/><c/></root>', @schema_nested) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 0, the final element is missing
|
||||
SELECT XMLISVALID('<root><a/><b/></root>', @schema_nested) AS r;
|
||||
r
|
||||
0
|
||||
# Expect 0, incomplete nested sequence
|
||||
SELECT XMLISVALID('<root><a/><c/></root>', @schema_nested) AS r;
|
||||
r
|
||||
0
|
||||
#
|
||||
# A nested xs:sequence followed by an optional element: the failed
|
||||
# probe of a new iteration must not be counted as an occurrence.
|
||||
#
|
||||
SET @schema_nested_min= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:sequence minOccurs="2" maxOccurs="2">
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><b/></root>', @schema_nested_min) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><b/><c/></root>', @schema_nested_min) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 0, only one occurrence of the nested sequence
|
||||
SELECT XMLISVALID('<root><a/><b/></root>', @schema_nested_min) AS r;
|
||||
r
|
||||
0
|
||||
# Expect 0, only one occurrence of the nested sequence, followed by c
|
||||
SELECT XMLISVALID('<root><a/><b/><c/></root>', @schema_nested_min) AS r;
|
||||
r
|
||||
0
|
||||
# Expect 0, second occurrence is incomplete
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><c/></root>', @schema_nested_min) AS r;
|
||||
r
|
||||
0
|
||||
SET @schema_nested_req= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a/></root>', @schema_nested_req) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 1
|
||||
SELECT XMLISVALID('<root><a/><c/></root>', @schema_nested_req) AS r;
|
||||
r
|
||||
1
|
||||
# Expect 0, required nested sequence is missing
|
||||
SELECT XMLISVALID('<root><c/></root>', @schema_nested_req) AS r;
|
||||
r
|
||||
0
|
||||
# Expect 0, required nested sequence is missing
|
||||
SELECT XMLISVALID('<root/>', @schema_nested_req) AS r;
|
||||
r
|
||||
0
|
||||
|
||||
@@ -1079,7 +1079,7 @@ set @xml= '
|
||||
<OrderDate>2026-06-01</OrderDate>
|
||||
</RegularOrder>';
|
||||
|
||||
select XMLISVALID(@xml, @schema);
|
||||
select XMLISVALID(@xml, @schema) Ex0;
|
||||
|
||||
set @schema= ' <?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
@@ -1128,7 +1128,7 @@ set @xml= '
|
||||
<OrderDate>2026-06-01</OrderDate>
|
||||
</RegularOrder>';
|
||||
|
||||
select XMLISVALID(@xml, @schema);
|
||||
select XMLISVALID(@xml, @schema) Ex1;
|
||||
|
||||
set @schema= ' <?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
@@ -1175,7 +1175,7 @@ set @xml= '
|
||||
<OrderDate>2026-06-01</OrderDate>
|
||||
</RegularOrder>';
|
||||
|
||||
select XMLISVALID(@xml, @schema);
|
||||
select XMLISVALID(@xml, @schema) Ex1;
|
||||
|
||||
set @schema= ' <?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
@@ -2236,3 +2236,606 @@ SELECT XMLISVALID( '<root>x</root>',
|
||||
</xs:simpleType>
|
||||
</xs:schema>' ) AS r;
|
||||
|
||||
--echo
|
||||
--echo MDEV-40394 XML schema fails on self-referencing type.
|
||||
--echo
|
||||
|
||||
SELECT XMLISVALID('
|
||||
<root>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> One </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<leaf> Two </leaf>
|
||||
</lt>
|
||||
<rt>
|
||||
<leaf> Three </leaf>
|
||||
</rt>
|
||||
</rt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> Four </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
</lt>
|
||||
</rt>
|
||||
</root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:all>
|
||||
<xs:element name="lt" type="T" minOccurs="0"/>
|
||||
<xs:element name="rt" type="T" minOccurs="0"/>
|
||||
<xs:element name="leaf" type="xs:string" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as V;
|
||||
|
||||
SELECT XMLISVALID('
|
||||
<root>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> One </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<leaf> Two </leaf>
|
||||
</lt>
|
||||
<rt>
|
||||
<leaf> Three </leaf>
|
||||
</rt>
|
||||
</rt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> Four </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
</lt>
|
||||
</rt>
|
||||
</root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:element name="lt" type="T" minOccurs="0"/>
|
||||
<xs:element name="rt" type="T" minOccurs="0"/>
|
||||
<xs:element name="leaf" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as Expect_1;
|
||||
|
||||
SELECT XMLISVALID('<root><child/></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence><xs:element name="child" type="T"/></xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as V;
|
||||
|
||||
SELECT XMLISVALID('<root><child> <child/> <child/></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence><xs:element name="child" type="T"/></xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as V;
|
||||
|
||||
SELECT XMLISVALID('<root><child> <child> <child> <child/> </child></child></child></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence minOccurs="0">
|
||||
<xs:element name="child" type="T"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as V;
|
||||
|
||||
--error ER_UNKNOWN_ERROR
|
||||
SELECT XMLISVALID('<root><x> a </x> </root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:group name="G">
|
||||
<xs:sequence>
|
||||
<xs:element name="x" type="xs:string"/>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence>
|
||||
</xs:group>
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') AS v;
|
||||
|
||||
--error ER_UNKNOWN_ERROR
|
||||
SELECT XMLISVALID('<root><x> a </x> </root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:group name="G">
|
||||
<xs:sequence>
|
||||
<xs:element name="x" type="xs:string"/>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence>
|
||||
</xs:group>
|
||||
<xs:element name="root">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
</xs:schema>') AS v;
|
||||
|
||||
|
||||
# Case A: recursive xs:all, valid doc, inner element name reused at parent.
|
||||
SELECT XMLISVALID('<root><self><x>i</x></self><x>o</x></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T"><xs:all>
|
||||
<xs:element name="x" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="self" type="T" minOccurs="0"/>
|
||||
</xs:all></xs:complexType>
|
||||
<xs:element name="root" type="T"/></xs:schema>') as A_expect_1;
|
||||
|
||||
# Case B: recursive xs:sequence, element maxOccurs=2, inner uses budget.
|
||||
SELECT XMLISVALID('<root><self><x>i1</x><x>i2</x></self><x>o1</x><x>o2</x></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:element name="self" type="T" minOccurs="0"/>
|
||||
<xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="2"/>
|
||||
</xs:sequence></xs:complexType>
|
||||
<xs:element name="root" type="T"/></xs:schema>') as B_expect_1;
|
||||
|
||||
# Case C: recursive xs:all, does it FALSE-ACCEPT a duplicate?
|
||||
SELECT XMLISVALID('<root><x>a</x><self></self><x>b</x></root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T"><xs:all>
|
||||
<xs:element name="x" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="self" type="T" minOccurs="0"/>
|
||||
</xs:all></xs:complexType>
|
||||
<xs:element name="root" type="T"/></xs:schema>') as C_expect_0;
|
||||
|
||||
SELECT XMLISVALID('
|
||||
<root>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<leaf> One </leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<leaf> Two </leaf>
|
||||
</lt>
|
||||
<rt>
|
||||
<leaf> Three </leaf>
|
||||
</rt>
|
||||
</rt>
|
||||
</lt>
|
||||
<rt>
|
||||
<lt>
|
||||
<lt>
|
||||
<lt>
|
||||
<BAD_leaf> Four </BAD_leaf>
|
||||
</lt>
|
||||
</lt>
|
||||
</lt>
|
||||
</rt>
|
||||
</root>',
|
||||
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:element name="lt" type="T" minOccurs="0"/>
|
||||
<xs:element name="rt" type="T" minOccurs="0"/>
|
||||
<xs:element name="leaf" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>') as Expect_0;
|
||||
|
||||
--echo #
|
||||
--echo # Recursion through a shared xs:group
|
||||
--echo # Every group_reference shares the group's single compositor, so a
|
||||
--echo # nested use of the group resets the state of the outer one.
|
||||
--echo #
|
||||
|
||||
SET @schema_group= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:group name="G">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="T2" minOccurs="0"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:group>
|
||||
<xs:complexType name="T1"><xs:sequence><xs:group ref="G"/></xs:sequence></xs:complexType>
|
||||
<xs:complexType name="T2"><xs:sequence><xs:group ref="G"/></xs:sequence></xs:complexType>
|
||||
<xs:element name="root" type="T1"/>
|
||||
</xs:schema>';
|
||||
|
||||
SET @schema_seq= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T1">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="T2" minOccurs="0"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="T2">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="T2" minOccurs="0"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T1"/>
|
||||
</xs:schema>';
|
||||
|
||||
--echo # Valid: nested <a> holds its own <b>, outer <b> follows. Expect 1
|
||||
--echo # (same structure without the group, for comparison, is also 1)
|
||||
SELECT XMLISVALID('<root><a><b>x</b></a><b>y</b></root>', @schema_group) AS group_valid,
|
||||
XMLISVALID('<root><a><b>x</b></a><b>y</b></root>', @schema_seq) AS seq_valid;
|
||||
|
||||
--echo # Valid, two levels deep. Expect 1 / 1
|
||||
SELECT XMLISVALID('<root><a><a><b>x</b></a><b>y</b></a><b>z</b></root>', @schema_group) AS group_valid,
|
||||
XMLISVALID('<root><a><a><b>x</b></a><b>y</b></a><b>z</b></root>', @schema_seq) AS seq_valid;
|
||||
|
||||
--echo # Invalid: outer <b> missing. Expect 0 / 0
|
||||
SELECT XMLISVALID('<root><a><b>x</b></a></root>', @schema_group) AS group_invalid,
|
||||
XMLISVALID('<root><a><b>x</b></a></root>', @schema_seq) AS seq_invalid;
|
||||
|
||||
--echo # Invalid: inner <b> missing. Expect 0 / 0
|
||||
SELECT XMLISVALID('<root><a></a><b>y</b></root>', @schema_group) AS group_invalid,
|
||||
XMLISVALID('<root><a></a><b>y</b></root>', @schema_seq) AS seq_invalid;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # xs:group reference occurrence counting.
|
||||
--echo # minOccurs/maxOccurs on a group reference, including an emptiable group.
|
||||
--echo #
|
||||
|
||||
SET @pre= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">';
|
||||
SET @post= '<xs:element name="c" type="xs:string"/></xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
|
||||
--echo # Group with required content, minOccurs=2 maxOccurs=2
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G" minOccurs="2" maxOccurs="2"/>', @post);
|
||||
|
||||
--echo # One occurrence: too few. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Two occurrences. Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><a>2</a><b>2</b><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Three occurrences: too many. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><a>2</a><b>2</b><a>3</a><b>3</b><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Second occurrence incomplete. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><a>2</a><c>x</c></root>', @schema_group) AS grp;
|
||||
|
||||
--echo # Group with minOccurs=0
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G" minOccurs="0"/>', @post);
|
||||
|
||||
--echo # Group absent. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Group present. Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Group present twice (maxOccurs defaults to 1). Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><b>1</b><a>2</a><b>2</b><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Group present but incomplete. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><c>x</c></root>', @schema_group) AS grp;
|
||||
|
||||
--echo # Group with minOccurs=1 maxOccurs=unbounded
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G" maxOccurs="unbounded"/>', @post);
|
||||
|
||||
--echo # Absent: too few. Expect 0
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Four occurrences. Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><b/><a/><b/><a/><b/><c>x</c></root>', @schema_group) AS grp;
|
||||
|
||||
--echo # Emptiable group (all particles optional), default minOccurs=1
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G"/>', @post);
|
||||
|
||||
--echo # Group content absent. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Group content present. Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><c>x</c></root>', @schema_group) AS grp;
|
||||
|
||||
--echo # Emptiable group, minOccurs=2 maxOccurs=3
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:group ref="G" minOccurs="2" maxOccurs="3"/>', @post);
|
||||
|
||||
--echo # Group content absent. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Three <a>. Expect 1
|
||||
SELECT XMLISVALID('<root><a/><a/><a/><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Four <a>: too many. Expect 0
|
||||
SELECT XMLISVALID('<root><a/><a/><a/><a/><c>x</c></root>', @schema_group) AS grp;
|
||||
|
||||
--echo # Emptiable group reference as the last particle of a sequence
|
||||
SET @schema_group= CONCAT(@pre, '
|
||||
<xs:group name="G"><xs:sequence>
|
||||
<xs:element name="a" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence></xs:group>
|
||||
<xs:complexType name="T"><xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
<xs:group ref="G"/>
|
||||
</xs:sequence></xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>');
|
||||
|
||||
--echo # Group content absent, no tag reaches the group reference. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c></root>', @schema_group) AS grp;
|
||||
--echo # Group content present. Expect 1
|
||||
SELECT XMLISVALID('<root><c>x</c><a>1</a></root>', @schema_group) AS grp;
|
||||
--echo # Required <c> missing. Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a></root>', @schema_group) AS grp;
|
||||
|
||||
--echo #
|
||||
--echo # recursion depth limit and recovery after aborted validation
|
||||
--echo #
|
||||
|
||||
SET @schema_rec= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:all>
|
||||
<xs:element name="c" type="T" minOccurs="0"/>
|
||||
<xs:element name="leaf" type="xs:string" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
|
||||
--echo # Just below the depth limit. Expect 1
|
||||
SELECT XMLISVALID(CONCAT('<root>', REPEAT('<c>', 1021), '<leaf>x</leaf>',
|
||||
REPEAT('</c>', 1021), '</root>'), @schema_rec) AS below_limit;
|
||||
--error ER_UNKNOWN_ERROR
|
||||
SELECT XMLISVALID(CONCAT('<root>', REPEAT('<c>', 1100), '<leaf>x</leaf>',
|
||||
REPEAT('</c>', 1100), '</root>'), @schema_rec) AS over_limit;
|
||||
|
||||
--echo # Rows after an aborted validation are not affected by it
|
||||
CREATE TABLE t1 (id INT, x LONGTEXT);
|
||||
INSERT INTO t1 VALUES
|
||||
(1, '<root><c><c><d/></c></c></root>'),
|
||||
(2, '<root><c><c><leaf>x</leaf></c></c></root>'),
|
||||
(3, '<root><c><c_bad><leaf>x</leaf></c></c></root>'),
|
||||
(4, '<root><c><c><leaf>x</leaf></c></c></root>'),
|
||||
(5, '<root><c><c><d/></c></c></root>'),
|
||||
(6, '<root><c><leaf>x</leaf></c></root>');
|
||||
SELECT id, XMLISVALID(x, @schema_rec) AS r FROM t1 ORDER BY id;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # Recursion through xs:choice
|
||||
SET @schema_rec= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:choice>
|
||||
<xs:element name="c" type="T"/>
|
||||
<xs:element name="leaf" type="xs:string"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><c><c><leaf>a</leaf></c></c></root>', @schema_rec) AS r;
|
||||
--echo # Expect 0
|
||||
SELECT XMLISVALID('<root><c><c><leaf>a</leaf><leaf>b</leaf></c></c></root>', @schema_rec) AS r;
|
||||
--echo # Expect 0
|
||||
SELECT XMLISVALID('<root><c><c><d/></c></c></root>', @schema_rec) AS r;
|
||||
|
||||
--echo # Recursion through an anonymous type
|
||||
SET @schema_rec= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence><xs:element name="b" type="T" minOccurs="0"/></xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="leaf" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a><b><a><b><leaf>x</leaf></b></a><leaf>y</leaf></b></a><leaf>z</leaf></root>', @schema_rec) AS r;
|
||||
--echo # Expect 0
|
||||
SELECT XMLISVALID('<root><a><b><a><b><leaf>x</leaf></b></a></b></a><leaf>z</leaf></root>', @schema_rec) AS r;
|
||||
|
||||
--echo # Choice with an unfinished nested compositor
|
||||
SET @schema_choice= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:choice>
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b></root>', @schema_choice) AS r;
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><c>1</c></root>', @schema_choice) AS r;
|
||||
--echo # Expect 0, the chosen sequence misses <b>
|
||||
SELECT XMLISVALID('<root><a>1</a></root>', @schema_choice) AS r;
|
||||
|
||||
--echo # The same, with the choice nested in a sequence
|
||||
SET @schema_choice= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:choice>
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:choice>
|
||||
<xs:element name="d" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b><d>3</d></root>', @schema_choice) AS r;
|
||||
--echo # Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a></root>', @schema_choice) AS r;
|
||||
--echo # Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a><d>3</d></root>', @schema_choice) AS r;
|
||||
|
||||
--echo # Choice alternative is a group holding an incomplete sequence
|
||||
SET @schema_choice= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:group name="G">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:group>
|
||||
<xs:complexType name="T">
|
||||
<xs:choice>
|
||||
<xs:group ref="G"/>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b></root>', @schema_choice) AS r;
|
||||
--echo # Expect 0
|
||||
SELECT XMLISVALID('<root><a>1</a></root>', @schema_choice) AS r;
|
||||
|
||||
--echo # Choice with maxOccurs>1: an alternative that was tried but not chosen
|
||||
--echo # must not leave stale state, so the repeated alternative is accepted
|
||||
SET @schema_choice= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:choice maxOccurs="3">
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b><c>3</c></root>', @schema_choice) AS r;
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><c>1</c><a>2</a><b>3</b></root>', @schema_choice) AS r;
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><c>1</c><c>2</c></root>', @schema_choice) AS r;
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><c>1</c><c>2</c><c>3</c></root>', @schema_choice) AS r;
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a>1</a><b>2</b><a>3</a><b>4</b></root>', @schema_choice) AS r;
|
||||
--echo # Expect 0, incomplete sequence alternative
|
||||
SELECT XMLISVALID('<root><c>1</c><a>2</a></root>', @schema_choice) AS r;
|
||||
--echo # Expect 0, four occurrences
|
||||
SELECT XMLISVALID('<root><c>1</c><c>2</c><c>3</c><c>4</c></root>', @schema_choice) AS r;
|
||||
|
||||
--echo #
|
||||
--echo # An unbounded nested xs:sequence followed by another element
|
||||
--echo # (existing bug in XMLSchema_sequence::validate_tag_name: the nested
|
||||
--echo # sequence takes the tag that belongs to the following element).
|
||||
--echo #
|
||||
SET @schema_nested= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:sequence maxOccurs="unbounded">
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><c/></root>', @schema_nested) AS r;
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><b/><c/></root>', @schema_nested) AS r;
|
||||
--echo # Expect 0, the final element is missing
|
||||
SELECT XMLISVALID('<root><a/><b/></root>', @schema_nested) AS r;
|
||||
--echo # Expect 0, incomplete nested sequence
|
||||
SELECT XMLISVALID('<root><a/><c/></root>', @schema_nested) AS r;
|
||||
|
||||
--echo #
|
||||
--echo # A nested xs:sequence followed by an optional element: the failed
|
||||
--echo # probe of a new iteration must not be counted as an occurrence.
|
||||
--echo #
|
||||
SET @schema_nested_min= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:sequence minOccurs="2" maxOccurs="2">
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
<xs:element name="b" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><b/></root>', @schema_nested_min) AS r;
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><b/><c/></root>', @schema_nested_min) AS r;
|
||||
--echo # Expect 0, only one occurrence of the nested sequence
|
||||
SELECT XMLISVALID('<root><a/><b/></root>', @schema_nested_min) AS r;
|
||||
--echo # Expect 0, only one occurrence of the nested sequence, followed by c
|
||||
SELECT XMLISVALID('<root><a/><b/><c/></root>', @schema_nested_min) AS r;
|
||||
--echo # Expect 0, second occurrence is incomplete
|
||||
SELECT XMLISVALID('<root><a/><b/><a/><c/></root>', @schema_nested_min) AS r;
|
||||
|
||||
SET @schema_nested_req= '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:complexType name="T">
|
||||
<xs:sequence>
|
||||
<xs:sequence>
|
||||
<xs:element name="a" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="c" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="root" type="T"/>
|
||||
</xs:schema>';
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a/></root>', @schema_nested_req) AS r;
|
||||
--echo # Expect 1
|
||||
SELECT XMLISVALID('<root><a/><c/></root>', @schema_nested_req) AS r;
|
||||
--echo # Expect 0, required nested sequence is missing
|
||||
SELECT XMLISVALID('<root><c/></root>', @schema_nested_req) AS r;
|
||||
--echo # Expect 0, required nested sequence is missing
|
||||
SELECT XMLISVALID('<root/>', @schema_nested_req) AS r;
|
||||
|
||||
Reference in New Issue
Block a user