mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-01 05:35:48 +00:00
Fix case Batch -> BATCH to match similar exception in same file Signed-off-by: Alejo Sanchez <alejo.sanchez@scylladb.com>
756 lines
14 KiB
Plaintext
756 lines
14 KiB
Plaintext
create table lwt (a int, b int, primary key (a,b));
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
-- basic batch: ok
|
|
begin batch
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true"
|
|
}
|
|
]
|
|
}
|
|
-- begin unlogged batch + lwt: ok; unlogged is ignored
|
|
-- (same in c*)
|
|
begin unlogged batch
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "false",
|
|
"a" : "1",
|
|
"b" : "1"
|
|
}
|
|
]
|
|
}
|
|
-- begin counter batch + lwt: error
|
|
begin counter batch
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (Cannot include non-counter statement in a counter batch)",
|
|
"status" : "error"
|
|
}
|
|
-- a batch affecting two partitions: error
|
|
begin batch
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
insert into lwt (a, b) values (2, 1) if not exists
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (BATCH with conditions cannot span multiple partitions)",
|
|
"status" : "error"
|
|
}
|
|
-- a batch with an LWT statement and other statement affecting another
|
|
-- partition: error
|
|
begin batch
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
insert into lwt (a, b) values (2, 1)
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (BATCH with conditions cannot span multiple partitions)",
|
|
"status" : "error"
|
|
}
|
|
-- a batch affecting different clustering keys of the same partition: ok
|
|
begin batch
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
insert into lwt (a, b) values (1, 2) if not exists
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "false",
|
|
"a" : "1",
|
|
"b" : "1"
|
|
}
|
|
]
|
|
}
|
|
-- a batch and non-batch statement, on the same partition: ok
|
|
begin batch
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
insert into lwt (a, b) values (1, 2)
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "false",
|
|
"a" : "1",
|
|
"b" : "1"
|
|
}
|
|
]
|
|
}
|
|
-- a batch affecting two tables: error
|
|
create table two (a int primary key, b int);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
begin batch
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
insert into two (a, b) values (1, 1)
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (BATCH with conditions cannot span multiple tables)",
|
|
"status" : "error"
|
|
}
|
|
drop table two;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
-- a batch with custom timestamp set: error
|
|
begin batch using timestamp 1
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (Cannot provide custom timestamp for conditional BATCH)",
|
|
"status" : "error"
|
|
}
|
|
-- a batch with a statement with a custom timestamp: error
|
|
begin batch
|
|
insert into lwt (a, b) values (1, 1) if not exists using timestamp 1
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (Cannot provide custom timestamp for conditional updates)",
|
|
"status" : "error"
|
|
}
|
|
-- a batch with an LWT statement and another statement with a custom timestamp set: ok
|
|
begin batch
|
|
insert into lwt (a, b) values (1, 1) if not exists
|
|
insert into lwt (a, b) values (1, 1) using timestamp 1
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "false",
|
|
"a" : "1",
|
|
"b" : "1"
|
|
}
|
|
]
|
|
}
|
|
-- a batch with if condition and counters: error
|
|
-- if a table has a counter, all its non-primary key columns
|
|
-- must be counters
|
|
create table lcounter (a int primary key, c counter);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
begin batch
|
|
update lcounter set c = c + 1 where a = 1 if c = null
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (Conditional updates are not supported on counter tables)",
|
|
"status" : "error"
|
|
}
|
|
drop table lcounter;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
drop table lwt;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
create table lwt (a int, b int, c int, primary key (a,b));
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
-- a batch with IF condition on primary key: error
|
|
begin batch
|
|
update lwt set c = 2 where a = 1 and b = 1 if a > 0
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (PRIMARY KEY column 'a' cannot have IF conditions)",
|
|
"status" : "error"
|
|
}
|
|
begin batch
|
|
update lwt set c = 2 where a = 1 and b = 1 if b > 0
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (PRIMARY KEY column 'b' cannot have IF conditions)",
|
|
"status" : "error"
|
|
}
|
|
begin batch
|
|
update lwt set c = 2 where a = 1 if c = null
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (Missing mandatory PRIMARY KEY part b)",
|
|
"status" : "error"
|
|
}
|
|
-- a batch with a statement that has IN prediacte and IF condition: error
|
|
begin batch
|
|
update lwt set c = 2 where a = 1 and b in (1, 2) if c = null
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (IN on the clustering key columns is not supported with conditional updates)",
|
|
"status" : "error"
|
|
}
|
|
-- a batch with a statement that has IN prediacte and *another* statement
|
|
-- with IF condition: OK. This is an error in C* but I see no reason
|
|
-- why it should be an error in Scylla.
|
|
delete from lwt where a = 1;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
begin batch
|
|
update lwt set c = 2 where a = 1 and b = 1 if c = null
|
|
update lwt set c = 2 where a = 1 and b in (1, 2)
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true"
|
|
}
|
|
]
|
|
}
|
|
select a, b, c from lwt where a = 1 and b in (1, 2);
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"a" : "1",
|
|
"b" : "1",
|
|
"c" : "2"
|
|
},
|
|
{
|
|
"a" : "1",
|
|
"b" : "2",
|
|
"c" : "2"
|
|
}
|
|
]
|
|
}
|
|
drop table lwt;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
--
|
|
-- BATCH LWT with multiple statements on LIST data type,
|
|
-- append/discard operations on the type: all append/discard
|
|
-- operations from all stsatemetns of the batch are applied
|
|
--
|
|
create table lwt (a int, b int, c list<text>, d list<text> static, primary key (a, b));
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
begin batch
|
|
insert into lwt (a, b, c, d ) values (1, 1, ['1'], ['1']) if not exists
|
|
insert into lwt (a, b, c, d ) values (1, 2, ['2'], ['2']) if not exists
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true"
|
|
}
|
|
]
|
|
}
|
|
select b, c, d from lwt where a = 1;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"b" : "1",
|
|
"c" : "[\"1\"]",
|
|
"d" : "[\"1\", \"2\"]"
|
|
},
|
|
{
|
|
"b" : "2",
|
|
"c" : "[\"2\"]",
|
|
"d" : "[\"1\", \"2\"]"
|
|
}
|
|
]
|
|
}
|
|
begin batch
|
|
update lwt set c = c + ['3'], d = d + ['3'] where a = 1 and b = 1 if exists
|
|
update lwt set c = c + ['4'], d = d + ['4'] where a = 1 and b = 2
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true",
|
|
"a" : "1",
|
|
"b" : "1",
|
|
"c" : "[\"1\"]",
|
|
"d" : "[\"1\", \"2\"]"
|
|
}
|
|
]
|
|
}
|
|
select b, c, d from lwt where a = 1;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"b" : "1",
|
|
"c" : "[\"1\", \"3\"]",
|
|
"d" : "[\"1\", \"2\", \"3\", \"4\"]"
|
|
},
|
|
{
|
|
"b" : "2",
|
|
"c" : "[\"2\", \"4\"]",
|
|
"d" : "[\"1\", \"2\", \"3\", \"4\"]"
|
|
}
|
|
]
|
|
}
|
|
begin batch
|
|
update lwt set c = c + ['5'], d = d + ['5'] where a = 1 and b = 1 if c[0] = '1' and c[1] = '3'
|
|
update lwt set c = c + ['6'], d = d + ['6'] where a = 1 and b = 2
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true",
|
|
"a" : "1",
|
|
"b" : "1",
|
|
"c" : "[\"1\", \"3\"]"
|
|
}
|
|
]
|
|
}
|
|
select b, c, d from lwt where a = 1;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"b" : "1",
|
|
"c" : "[\"1\", \"3\", \"5\"]",
|
|
"d" : "[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]"
|
|
},
|
|
{
|
|
"b" : "2",
|
|
"c" : "[\"2\", \"4\", \"6\"]",
|
|
"d" : "[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]"
|
|
}
|
|
]
|
|
}
|
|
-- multiple conditions:
|
|
-- two simple conditions, effects of all statements are applied atomically
|
|
-- or not applied at all: ok
|
|
begin batch
|
|
update lwt set c = c + ['7'], d = d + ['7'] where a = 1 and b = 1 if c[0] = '1' and c[1] = '2'
|
|
update lwt set c = c + ['8'], d = d + ['8'] where a = 1 and b = 2 if c[3] = '3' and c[4] = '4'
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "false",
|
|
"a" : "1",
|
|
"b" : "1",
|
|
"c" : "[\"1\", \"3\", \"5\"]"
|
|
},
|
|
{
|
|
"[applied]" : "false",
|
|
"a" : "1",
|
|
"b" : "2",
|
|
"c" : "[\"2\", \"4\", \"6\"]"
|
|
}
|
|
]
|
|
}
|
|
select b, c, d from lwt where a = 1;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"b" : "1",
|
|
"c" : "[\"1\", \"3\", \"5\"]",
|
|
"d" : "[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]"
|
|
},
|
|
{
|
|
"b" : "2",
|
|
"c" : "[\"2\", \"4\", \"6\"]",
|
|
"d" : "[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]"
|
|
}
|
|
]
|
|
}
|
|
begin batch
|
|
update lwt set c = c + ['7'], d = d + ['7'] where a = 1 and b = 1 if c[0] = '1' and c[1] = '3'
|
|
update lwt set c = c + ['8'], d = d + ['8'] where a = 1 and b = 2 if c[1] = '4' and c[2] = '6'
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true",
|
|
"a" : "1",
|
|
"b" : "1",
|
|
"c" : "[\"1\", \"3\", \"5\"]"
|
|
},
|
|
{
|
|
"[applied]" : "true",
|
|
"a" : "1",
|
|
"b" : "2",
|
|
"c" : "[\"2\", \"4\", \"6\"]"
|
|
}
|
|
]
|
|
}
|
|
select b, c, d from lwt where a = 1;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"b" : "1",
|
|
"c" : "[\"1\", \"3\", \"5\", \"7\"]",
|
|
"d" : "[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\"]"
|
|
},
|
|
{
|
|
"b" : "2",
|
|
"c" : "[\"2\", \"4\", \"6\", \"8\"]",
|
|
"d" : "[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\"]"
|
|
}
|
|
]
|
|
}
|
|
drop table lwt;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
|
|
-- batch + lwt + range UPDATE of multiple rows, clustering key is not fully restricted: ok
|
|
-- batch + lwt + range DELETE of multiple rows, clustering key is not fully restricted: ok
|
|
-- usually within the same partition key
|
|
create table lwt (a int, b int, c int, d int, primary key (a, b, c));
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt (a, b, c, d) values (1,1,1,1);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt (a, b, c, d) values (1,1,2,0);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt (a, b, c, d) values (1,1,3,1);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt (a, b, c, d) values (1,2,1,1);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt (a, b, c, d) values (1,2,2,0);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt (a, b, c, d) values (1,2,3,1);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
-- update
|
|
begin batch
|
|
update lwt set d = 7 where a = 1 and b = 1 and c = 1 if exists
|
|
update lwt set d = 7 where a = 1 and b in (1,2) and c in (1,2,3)
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true",
|
|
"a" : "1",
|
|
"b" : "1",
|
|
"c" : "1",
|
|
"d" : "1"
|
|
}
|
|
]
|
|
}
|
|
select a, b, c, d from lwt where a = 1;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"a" : "1",
|
|
"b" : "1",
|
|
"c" : "1",
|
|
"d" : "7"
|
|
},
|
|
{
|
|
"a" : "1",
|
|
"b" : "1",
|
|
"c" : "2",
|
|
"d" : "7"
|
|
},
|
|
{
|
|
"a" : "1",
|
|
"b" : "1",
|
|
"c" : "3",
|
|
"d" : "7"
|
|
},
|
|
{
|
|
"a" : "1",
|
|
"b" : "2",
|
|
"c" : "1",
|
|
"d" : "7"
|
|
},
|
|
{
|
|
"a" : "1",
|
|
"b" : "2",
|
|
"c" : "2",
|
|
"d" : "7"
|
|
},
|
|
{
|
|
"a" : "1",
|
|
"b" : "2",
|
|
"c" : "3",
|
|
"d" : "7"
|
|
}
|
|
]
|
|
}
|
|
-- delete
|
|
begin batch
|
|
delete from lwt where a = 1 and b = 1 if exists
|
|
delete from lwt where a = 1 and b = 2 if exists
|
|
apply batch;
|
|
{
|
|
"message" : "exceptions::invalid_request_exception (DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns)",
|
|
"status" : "error"
|
|
}
|
|
-- select a, b, c, d from lwt where a = 1;
|
|
drop table lwt;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
|
|
-- Rows fetched for statements that require read but has no conditions
|
|
-- must not be included into the result set.
|
|
create table lwt(p int, c int, i int, l list<int>, primary key(p, c));
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt(p, c, i, l) values(1, 1, 1, [1, 2]);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt(p, c, i, l) values(1, 2, 2, [1, 2, 3, 4]);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
-- doesn't apply
|
|
begin batch
|
|
update lwt set i = 3 where p = 1 and c = 1 if i = 2
|
|
update lwt set l = l - [1] where p = 1 and c = 2
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "false",
|
|
"c" : "1",
|
|
"i" : "1",
|
|
"p" : "1"
|
|
}
|
|
]
|
|
}
|
|
-- applies
|
|
begin batch
|
|
update lwt set i = 2 where p = 1 and c = 1 if i = 1
|
|
update lwt set l = l - [2] where p = 1 and c = 2
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true",
|
|
"c" : "1",
|
|
"i" : "1",
|
|
"p" : "1"
|
|
}
|
|
]
|
|
}
|
|
-- doesn't apply
|
|
begin batch
|
|
delete l from lwt where p = 1 and c = 3 if exists
|
|
update lwt set l = l - [3] where p = 1 and c = 2
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "false"
|
|
}
|
|
]
|
|
}
|
|
-- applies
|
|
begin batch
|
|
delete l from lwt where p = 1 and c = 1 if exists
|
|
update lwt set l = l - [4] where p = 1 and c = 2
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true",
|
|
"c" : "1",
|
|
"i" : "2",
|
|
"l" : "[1, 2]",
|
|
"p" : "1"
|
|
}
|
|
]
|
|
}
|
|
select * from lwt;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"c" : "1",
|
|
"i" : "2",
|
|
"p" : "1"
|
|
},
|
|
{
|
|
"c" : "2",
|
|
"i" : "2",
|
|
"l" : "[1, 3]",
|
|
"p" : "1"
|
|
}
|
|
]
|
|
}
|
|
drop table lwt;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
|
|
-- Suppose there's a batch with two statements, one of which has clustering
|
|
-- column restrictions that select no row, another has static conditions.
|
|
-- In this case we must fetch the static row (provided it exists, of course)
|
|
-- to check the static column conditions.
|
|
create table lwt (p int, c int, s int static, primary key (p, c));
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt(p, s) values(1, 1);
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
begin batch
|
|
insert into lwt(p, c) values(1, 1) if not exists
|
|
update lwt set s = 2 where p = 1 if s = 1
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true",
|
|
"p" : "1",
|
|
"s" : "1"
|
|
}
|
|
]
|
|
}
|
|
select * from lwt;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"c" : "1",
|
|
"p" : "1",
|
|
"s" : "2"
|
|
}
|
|
]
|
|
}
|
|
drop table lwt;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
--
|
|
--
|
|
-- condtitions on different list columns and different rows of the same
|
|
-- partition, these columns are retreived fine and the appropriate row
|
|
-- is found when checking the conds
|
|
--
|
|
-- correct read command: statement 1 condition is on column a and list update
|
|
-- is on column b, while statement b condition is on column c and list
|
|
-- update is on column d
|
|
-- a composite read command is built and both rows are retreieved,
|
|
-- conditions are executed correctly and mutations are applied accordingly
|
|
--
|
|
--
|
|
-- Issue: #6273
|
|
-- Delete have priority above Insert.
|
|
create table lwt (key bigint, ck int, cv set<text>, PRIMARY KEY((key), ck));
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt (key, ck, cv) values (1, 0, {'a', 'b'}) if not exists;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true"
|
|
}
|
|
]
|
|
}
|
|
begin batch
|
|
delete from lwt where key=1 and ck=0 if exists
|
|
insert into lwt (key, ck, cv) values (1, 0, {'b', 'c'})
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true",
|
|
"ck" : "0",
|
|
"cv" : "[\"a\", \"b\"]",
|
|
"key" : "1"
|
|
}
|
|
]
|
|
}
|
|
select * from lwt;
|
|
{
|
|
"rows" : null
|
|
}
|
|
drop table lwt;
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
--
|
|
-- Workaround for Issue #6273.
|
|
-- Delete individual cells instead of entire partition.
|
|
--
|
|
create table lwt (key bigint, ck int, cv set<text>, PRIMARY KEY((key), ck));
|
|
{
|
|
"status" : "ok"
|
|
}
|
|
insert into lwt (key, ck, cv) values (1, 0, {'a', 'b'}) if not exists;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true"
|
|
}
|
|
]
|
|
}
|
|
begin batch
|
|
update lwt set cv=null where key=1 and ck=0 if exists
|
|
insert into lwt (key, ck, cv) values (1, 0, {'b', 'c'})
|
|
apply batch;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"[applied]" : "true",
|
|
"ck" : "0",
|
|
"cv" : "[\"a\", \"b\"]",
|
|
"key" : "1"
|
|
}
|
|
]
|
|
}
|
|
select * from lwt;
|
|
{
|
|
"rows" :
|
|
[
|
|
{
|
|
"ck" : "0",
|
|
"cv" : "[\"b\", \"c\"]",
|
|
"key" : "1"
|
|
}
|
|
]
|
|
}
|
|
drop table lwt;
|
|
{
|
|
"status" : "ok"
|
|
}
|