|
20 | 20 | package org.apache.iotdb.session; |
21 | 21 |
|
22 | 22 | import org.apache.iotdb.common.rpc.thrift.TEndPoint; |
| 23 | +import org.apache.iotdb.common.rpc.thrift.TSStatus; |
23 | 24 | import org.apache.iotdb.isession.SessionConfig; |
24 | 25 | import org.apache.iotdb.rpc.IoTDBConnectionException; |
25 | 26 | import org.apache.iotdb.rpc.RedirectException; |
26 | 27 | import org.apache.iotdb.rpc.StatementExecutionException; |
| 28 | +import org.apache.iotdb.rpc.TSStatusCode; |
27 | 29 | import org.apache.iotdb.service.rpc.thrift.TSInsertRecordReq; |
28 | 30 | import org.apache.iotdb.service.rpc.thrift.TSInsertRecordsOfOneDeviceReq; |
29 | 31 | import org.apache.iotdb.service.rpc.thrift.TSInsertRecordsReq; |
|
44 | 46 |
|
45 | 47 | import java.time.ZoneId; |
46 | 48 | import java.util.ArrayList; |
| 49 | +import java.util.Arrays; |
47 | 50 | import java.util.HashMap; |
48 | 51 | import java.util.List; |
49 | 52 | import java.util.Map; |
50 | 53 | import java.util.Random; |
| 54 | +import java.util.concurrent.atomic.AtomicBoolean; |
51 | 55 |
|
52 | 56 | import static org.junit.Assert.assertEquals; |
53 | 57 | import static org.junit.Assert.assertNull; |
@@ -705,6 +709,79 @@ public void testInsertRelationalTablet() |
705 | 709 | session.close(); |
706 | 710 | } |
707 | 711 |
|
| 712 | + @Test |
| 713 | + public void testGroupedRelationalTabletPreservesStatementFailures() throws Exception { |
| 714 | + AtomicBoolean failWrites = new AtomicBoolean(); |
| 715 | + session = |
| 716 | + new MockSession("127.0.0.1", 55560, true, "table") { |
| 717 | + @Override |
| 718 | + public SessionConnection constructSessionConnection( |
| 719 | + Session owner, TEndPoint endpoint, ZoneId zoneId) { |
| 720 | + return new MockSessionConnection(owner, endpoint, zoneId) { |
| 721 | + @Override |
| 722 | + protected void insertTablet(TSInsertTabletReq request) |
| 723 | + throws RedirectException, IoTDBConnectionException, StatementExecutionException { |
| 724 | + if (failWrites.get()) { |
| 725 | + TSStatusCode code = |
| 726 | + endpoint.getPort() == 55560 |
| 727 | + ? TSStatusCode.METADATA_ERROR |
| 728 | + : TSStatusCode.DATA_TYPE_MISMATCH; |
| 729 | + throw new StatementExecutionException( |
| 730 | + new TSStatus(code.getStatusCode()).setMessage("incompatible field")); |
| 731 | + } |
| 732 | + super.insertTablet(request); |
| 733 | + } |
| 734 | + }; |
| 735 | + } |
| 736 | + }; |
| 737 | + session.open(); |
| 738 | + try { |
| 739 | + Tablet tablet = |
| 740 | + new Tablet( |
| 741 | + "table1", |
| 742 | + Arrays.asList("id", "field"), |
| 743 | + Arrays.asList(TSDataType.STRING, TSDataType.INT64), |
| 744 | + Arrays.asList(ColumnCategory.TAG, ColumnCategory.FIELD), |
| 745 | + 50); |
| 746 | + for (int i = 0; i < 50; i++) { |
| 747 | + int row = tablet.getRowSize(); |
| 748 | + tablet.addTimestamp(row, row); |
| 749 | + tablet.addValue("id", row, "id" + (row % 4)); |
| 750 | + tablet.addValue("field", row, 1L); |
| 751 | + } |
| 752 | + session.insertRelationalTablet(tablet); |
| 753 | + assertEquals(4, session.tableModelDeviceIdToEndpoint.size()); |
| 754 | + |
| 755 | + failWrites.set(true); |
| 756 | + tablet.reset(); |
| 757 | + for (int i = 0; i < 4; i++) { |
| 758 | + int row = tablet.getRowSize(); |
| 759 | + tablet.addTimestamp(row, row); |
| 760 | + tablet.addValue("id", row, "id" + row); |
| 761 | + tablet.addValue("field", row, 1L); |
| 762 | + } |
| 763 | + StatementExecutionException failure = |
| 764 | + Assert.assertThrows( |
| 765 | + StatementExecutionException.class, () -> session.insertRelationalTablet(tablet)); |
| 766 | + assertEquals(4, failure.getSuppressed().length); |
| 767 | + long metadataFailures = 0; |
| 768 | + long typeFailures = 0; |
| 769 | + for (Throwable cause : failure.getSuppressed()) { |
| 770 | + Assert.assertTrue(cause instanceof StatementExecutionException); |
| 771 | + int code = ((StatementExecutionException) cause).getStatusCode(); |
| 772 | + if (code == TSStatusCode.METADATA_ERROR.getStatusCode()) { |
| 773 | + metadataFailures++; |
| 774 | + } else if (code == TSStatusCode.DATA_TYPE_MISMATCH.getStatusCode()) { |
| 775 | + typeFailures++; |
| 776 | + } |
| 777 | + } |
| 778 | + assertEquals(1, metadataFailures); |
| 779 | + assertEquals(3, typeFailures); |
| 780 | + } finally { |
| 781 | + session.close(); |
| 782 | + } |
| 783 | + } |
| 784 | + |
708 | 785 | @Test |
709 | 786 | public void testInsertRecordsWithSessionBroken() throws StatementExecutionException { |
710 | 787 | // without leader cache |
@@ -1281,7 +1358,7 @@ protected void insertRecordsOfOneDevice(TSInsertRecordsOfOneDeviceReq request) |
1281 | 1358 |
|
1282 | 1359 | @Override |
1283 | 1360 | protected void insertTablet(TSInsertTabletReq request) |
1284 | | - throws RedirectException, IoTDBConnectionException { |
| 1361 | + throws RedirectException, IoTDBConnectionException, StatementExecutionException { |
1285 | 1362 | if (isConnectionBroken()) { |
1286 | 1363 | throw ioTDBConnectionException; |
1287 | 1364 | } |
|
0 commit comments