@@ -2788,4 +2788,140 @@ attributes {
2788
2788
)" ,
2789
2789
}, request, Ydb::StatusIds::SUCCESS, " /MyRoot" , false , " " , " " , {}, true );
2790
2790
}
2791
+
2792
+ Y_UNIT_TEST (DecimalOutOfRange) {
2793
+ TTestBasicRuntime runtime;
2794
+ TTestEnv env (runtime);
2795
+ ui64 txId = 100 ;
2796
+
2797
+ TestCreateTable (runtime, ++txId, " /MyRoot" , R"(
2798
+ Name: "Table1"
2799
+ Columns { Name: "key" Type: "Uint64" }
2800
+ Columns { Name: "value" Type: "Decimal" }
2801
+ KeyColumnNames: ["key"]
2802
+ )" );
2803
+ env.TestWaitNotification (runtime, txId);
2804
+
2805
+ // Write a normal decimal value
2806
+ // 10.0^13-1 (scale 9) = 0x21e19e0c9ba76a53600
2807
+ {
2808
+ ui64 key = 1u ;
2809
+ std::pair<ui64, i64 > value = { 0x19e0c9ba76a53600ULL , 0x21eULL };
2810
+ UploadRow (runtime, " /MyRoot/Table1" , 0 , {1 }, {2 }, {TCell::Make (key)}, {TCell::Make (value)});
2811
+ }
2812
+ // Write a decimal value that is out of range for precision 22
2813
+ // 10.0^13 (scale 9) = 10^22 = 0x21e19e0c9bab2400000
2814
+ {
2815
+ ui64 key = 2u ;
2816
+ std::pair<ui64, i64 > value = { 0x19e0c9bab2400000ULL , 0x21eULL };
2817
+ UploadRow (runtime, " /MyRoot/Table1" , 0 , {1 }, {2 }, {TCell::Make (key)}, {TCell::Make (value)});
2818
+ }
2819
+
2820
+ TPortManager portManager;
2821
+ const ui16 port = portManager.GetPort ();
2822
+
2823
+ TS3Mock s3Mock ({}, TS3Mock::TSettings (port));
2824
+ UNIT_ASSERT (s3Mock.Start ());
2825
+
2826
+ TestExport (runtime, ++txId, " /MyRoot" , Sprintf (R"(
2827
+ ExportToS3Settings {
2828
+ endpoint: "localhost:%d"
2829
+ scheme: HTTP
2830
+ items {
2831
+ source_path: "/MyRoot/Table1"
2832
+ destination_prefix: "Backup1"
2833
+ }
2834
+ }
2835
+ )" , port));
2836
+ env.TestWaitNotification (runtime, txId);
2837
+
2838
+ TestGetExport (runtime, txId, " /MyRoot" , Ydb::StatusIds::SUCCESS);
2839
+
2840
+ {
2841
+ auto it = s3Mock.GetData ().find (" /Backup1/data_00.csv" );
2842
+ UNIT_ASSERT (it != s3Mock.GetData ().end ());
2843
+ UNIT_ASSERT_STRINGS_EQUAL (it->second ,
2844
+ " 1,9999999999999\n "
2845
+ " 2,10000000000000\n " );
2846
+ }
2847
+
2848
+ TestImport (runtime, ++txId, " /MyRoot" , Sprintf (R"(
2849
+ ImportFromS3Settings {
2850
+ endpoint: "localhost:%d"
2851
+ scheme: HTTP
2852
+ items {
2853
+ source_prefix: "Backup1"
2854
+ destination_path: "/MyRoot/Table2"
2855
+ }
2856
+ }
2857
+ )" , port));
2858
+ env.TestWaitNotification (runtime, txId);
2859
+
2860
+ TestGetImport (runtime, txId, " /MyRoot" , Ydb::StatusIds::SUCCESS);
2861
+
2862
+ TestExport (runtime, ++txId, " /MyRoot" , Sprintf (R"(
2863
+ ExportToS3Settings {
2864
+ endpoint: "localhost:%d"
2865
+ scheme: HTTP
2866
+ items {
2867
+ source_path: "/MyRoot/Table2"
2868
+ destination_prefix: "Backup2"
2869
+ }
2870
+ }
2871
+ )" , port));
2872
+ env.TestWaitNotification (runtime, txId);
2873
+
2874
+ TestGetExport (runtime, txId, " /MyRoot" , Ydb::StatusIds::SUCCESS);
2875
+
2876
+ // Note: out-of-range values are restored as inf
2877
+ {
2878
+ auto it = s3Mock.GetData ().find (" /Backup2/data_00.csv" );
2879
+ UNIT_ASSERT (it != s3Mock.GetData ().end ());
2880
+ UNIT_ASSERT_STRINGS_EQUAL (it->second ,
2881
+ " 1,9999999999999\n "
2882
+ " 2,inf\n " );
2883
+ }
2884
+ }
2885
+
2886
+ Y_UNIT_TEST (CorruptedDecimalValue) {
2887
+ TTestBasicRuntime runtime;
2888
+ TTestEnv env (runtime);
2889
+ ui64 txId = 100 ;
2890
+
2891
+ TestCreateTable (runtime, ++txId, " /MyRoot" , R"(
2892
+ Name: "Table1"
2893
+ Columns { Name: "key" Type: "Uint64" }
2894
+ Columns { Name: "value" Type: "Decimal" }
2895
+ KeyColumnNames: ["key"]
2896
+ )" );
2897
+ env.TestWaitNotification (runtime, txId);
2898
+
2899
+ // Write a decimal value that is way out of range for max precision 35
2900
+ // 10^38 = 0x4b3b4ca85a86c47a098a224000000000
2901
+ {
2902
+ ui64 key = 1u ;
2903
+ std::pair<ui64, i64 > value = { 0x098a224000000000ULL , 0x4b3b4ca85a86c47aULL };
2904
+ UploadRow (runtime, " /MyRoot/Table1" , 0 , {1 }, {2 }, {TCell::Make (key)}, {TCell::Make (value)});
2905
+ }
2906
+
2907
+ TPortManager portManager;
2908
+ const ui16 port = portManager.GetPort ();
2909
+
2910
+ TS3Mock s3Mock ({}, TS3Mock::TSettings (port));
2911
+ UNIT_ASSERT (s3Mock.Start ());
2912
+
2913
+ TestExport (runtime, ++txId, " /MyRoot" , Sprintf (R"(
2914
+ ExportToS3Settings {
2915
+ endpoint: "localhost:%d"
2916
+ scheme: HTTP
2917
+ items {
2918
+ source_path: "/MyRoot/Table1"
2919
+ destination_prefix: "Backup1"
2920
+ }
2921
+ }
2922
+ )" , port));
2923
+ env.TestWaitNotification (runtime, txId);
2924
+
2925
+ TestGetExport (runtime, txId, " /MyRoot" , Ydb::StatusIds::CANCELLED);
2926
+ }
2791
2927
}
0 commit comments