From 44a72b4dd2b64cb3585b36ace28040bd50b5c9db Mon Sep 17 00:00:00 2001 From: Anil Sahoo Date: Thu, 20 Jul 2023 17:57:17 +0530 Subject: [PATCH] 1. Added Expression to CREATE INDEX. #2595 2. Added support for ALTER INDEX column statistics. #6375 --- docs/en_US/images/index_columns.png | Bin 0 -> 14824 bytes docs/en_US/images/index_definition.png | Bin 72664 -> 16573 bytes docs/en_US/images/index_general.png | Bin 19558 -> 7139 bytes docs/en_US/images/index_sql.png | Bin 27305 -> 15635 bytes docs/en_US/index_dialog.rst | 28 +- .../schemas/tables/indexes/static/js/index.js | 7 +- .../tables/indexes/static/js/index.ui.js | 286 ++++++++------ .../tests/11_plus/alter_expr_statistics.sql | 14 + .../11_plus/alter_name_fillfactor_comment.sql | 16 + .../alter_reset_fillfactor_cluster.sql | 12 + .../11_plus/create_btree_asc_null_first.sql | 14 + .../create_btree_asc_null_first_msql.sql | 10 + .../11_plus/create_btree_asc_null_last.sql | 14 + .../create_btree_asc_null_last_msql.sql | 10 + .../11_plus/create_btree_desc_null_first.sql | 9 + .../create_btree_desc_null_first_msql.sql | 5 + .../11_plus/create_btree_desc_null_last.sql | 14 + .../create_btree_desc_null_last_msql.sql | 10 + .../create_btree_expr_asc_null_last.sql | 14 + .../create_btree_expr_asc_null_last_msql.sql | 10 + .../indexes/tests/11_plus/test_indexes.json | 364 ++++++++++++++++++ .../13_plus/create_btree_asc_null_first.sql | 1 + .../create_btree_asc_null_first_msql.sql | 1 + .../13_plus/create_btree_asc_null_last.sql | 1 + .../create_btree_asc_null_last_msql.sql | 1 + .../13_plus/create_btree_desc_null_last.sql | 1 + .../create_btree_desc_null_last_msql.sql | 1 + .../indexes/tests/13_plus/test_indexes.json | 101 ++++- .../15_plus/alter_name_fillfactor_comment.sql | 1 + .../alter_reset_fillfactor_cluster.sql | 1 + .../15_plus/create_btree_asc_null_first.sql | 1 + .../create_btree_asc_null_first_msql.sql | 1 + .../15_plus/create_btree_asc_null_last.sql | 1 + .../create_btree_asc_null_last_msql.sql | 1 + .../15_plus/create_btree_desc_null_first.sql | 1 + .../create_btree_desc_null_first_msql.sql | 1 + .../15_plus/create_btree_desc_null_last.sql | 1 + .../create_btree_desc_null_last_msql.sql | 1 + .../indexes/tests/15_plus/test_indexes.json | 74 ++++ .../tests/default/alter_expr_statistics.sql | 13 + .../default/alter_expr_statistics_msql.sql | 2 + .../create_btree_expr_asc_null_last.sql | 13 + .../create_btree_expr_asc_null_last_msql.sql | 9 + .../indexes/tests/default/test_indexes.json | 69 ++++ .../tables/indexes/tests/index_test_data.json | 53 ++- .../tables/indexes/tests/test_indexes_put.py | 11 + .../databases/schemas/tables/indexes/utils.py | 34 +- .../indexes/sql/11_plus/column_details.sql | 2 + .../templates/indexes/sql/11_plus/create.sql | 2 +- .../templates/indexes/sql/15_plus/create.sql | 2 +- .../indexes/sql/default/column_details.sql | 2 + .../templates/indexes/sql/default/create.sql | 2 +- .../templates/indexes/sql/default/update.sql | 9 + .../servers/static/js/privilege.ui.js | 2 +- .../static/js/SchemaView/DataGridView.jsx | 54 ++- .../schema_ui_files/index.ui.spec.js | 202 +++++++--- 56 files changed, 1270 insertions(+), 239 deletions(-) create mode 100644 docs/en_US/images/index_columns.png create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_expr_statistics.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_name_fillfactor_comment.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_reset_fillfactor_cluster.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_first.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_first_msql.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_last.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_last_msql.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_first.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_first_msql.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_last.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_last_msql.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_expr_asc_null_last.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_expr_asc_null_last_msql.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/test_indexes.json create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/alter_expr_statistics.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/alter_expr_statistics_msql.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_btree_expr_asc_null_last.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_btree_expr_asc_null_last_msql.sql diff --git a/docs/en_US/images/index_columns.png b/docs/en_US/images/index_columns.png new file mode 100644 index 0000000000000000000000000000000000000000..d344be56895816967df02ccb90b8e9a2d8d80872 GIT binary patch literal 14824 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 literal 0 HcmV?d00001 diff --git a/docs/en_US/images/index_definition.png b/docs/en_US/images/index_definition.png index 589a342b44759f3baf2480605e1a7b2166a7904b..a524b5af4a8d8aae48d34f56c03bbe291291cec7 100644 GIT binary patch literal 16573 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 literal 72664 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

#8 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 YA5Nmk>=z<}GXMYp07*qoM6N<$f@Pi@lmGw# diff --git a/docs/en_US/images/index_general.png b/docs/en_US/images/index_general.png index 133f05857cbde069eec38d3d3e19ba8f0a81ff90..c7e7cb373befb3fd954de5627b4c806a7344eac1 100644 GIT binary patch literal 7139 zcmbtZS5#AtvPMx*2%soEfPjFg6zNS+6qK&?mSCg^gkBRV79deTkPcD>mEKF}Ae$mx z2rWPYp?5+FAoc2h{&VibdAR4^`!wJ5*|TQ$?6vm$CpwSlXxM2eC@AREA3xNipg0Rq zP@E~fK>1rD-6Hq?H~IKP%RqH?ee2-xki5I6Y!kM)yf(kMy1BJ;dV0FLwt0MfJUTYH zyt?tDYhYk#VqtM*fBzSzwqh)o>zjrynI6sA*HMjomN%THUNM3ZM?&GmmD!Py@QM?T3>uK zi*sL@s>Ab@J*1%EpjUr*-vBYTn&M=YTg4pwroZJO&C5IQk-8#l-Dtw;>ESwk<UC{<37&D$2=s=ebkNTST47-j>ik~evXuEym(BUh=bbMM`h7s)3^~Qa zK2-RpUnEBOsXwRWht){OT*z*i-}`)MKJJ+tNOy!|Zf( zaE%SvW0+fTyXmqen=8Tlp4P>Ioj-yPrd5S|+W4e?Vgny(3PtR`@$V)9cSlLU@ocs! z2@B@;nV%I=hzkx+PqZeCf4WAOZ=RbtT2NYShp^_=* z96(th1{c37yDgYPWehuK+Z}2-+aYA^qyF4uJGq!0+LnhM36HX2LJMwb@{y00g5Mgq zKwcm4HrrmEUId=5l^OcZS+a8F5~Tny@_w;E^wT6ahxRv*B*r9bt}|Zs&g2uPHdeX_ zx!|@%ObCvzc7?ais=3Z+vofKWvPI#Ms@DbEJ&JY@kMFeHwc6i2IXNNfvQ9(`q7G3J zah>&gnPFyg_2f*aEfbBH8aGK@rPXx*B)S&BC`{x2xtU$YqNnK%2;65fvFE$u86d8~ z7J+0}S5%6dY-iN|@;p=LY>Yuf+b3qN(Qs-MQy3*Na{C3hlGv&Ms_c%ypu4CTSk3?Z zv&p3AQAI7G3=5>o02#QO8NtBB|MgPr+k|_}+?APdn}N(BU+jmml{(zx)0e^(ETfY} zZwQc>-1#jobFDLmCDbJ-yz@z3O^zxp(VhAJ4}wsH!db79eS|fcA53+LN1*q}g*D(@ zKvI@wOFj2Xvv^+#({>(_cMmKsjorKaZLt00b;jY#8uDr#mp&uckXT>4C60;9*`Y;` z_v=JQ+6eb1V)L$~`ZtmIMqMGKV3mmROXQ>>Oj1O{4ci?`)TGX%&xM41TEIth;!-x7 zgr6~<2gt@rgzYh8{zN~$Va*zRKm$MmReFpbz!2v3?-Y+So=Ei5u+pC_{pU@jqDvZVbAFqb+}t7+g%@%*uAnQ~}@pT?ETo`jnblMs*7n zmTM14>vI7YhaHvzraIM!UGl2Ju%`nY-Z7KAq+6FTjR9u+68>bjYrZ}bP5 zmxAP4CD7FnQ<_3tvp75gT8D*Hm z`Lf`XMA%jck*>RKXxbm8d9HiRo`!#!`NQ1eRdbcZdP=+*hrvq7zE@hglEX)o%uH?5z0Slm?n#p1E7 z3MJ4jl=CpHm(^BJ{qx13{-2UchsDlY;9W)g&hII3eOG1$|T9WghAsq-{E2ui5QB)f7A4D-Z_s!i$2R0w@Q zvop7*Q!dgl_fhS~tP;AUFZq03C|$3yevPYeYMNlhbdea$8bO4Vtt%3zSeLBUc5|1H z#N8{P%qKs@Xvn%^6TH87_K>t&iry4cmR@#XJ?VQTI*^87WA+j*X_=1*-BGq?^%4ec zaIFI8iyDV-3~r3Hkh~3BbsLRtO}xy$_4D_W3WVP8k?ms;4^u(?wfDct4-#m^ujC=V zoOvZtqRuRe%L~h^d#Nvuc%G2&w(StNZHst+`e1L~P}KPM_7gxp++uYiI3T!DG;Q zH!~kuquMAy-gb5Pk>27UJtRJ$JQ8R6vM%q`S4{B+CCFnX$b<%az4g7P5L|H9@Sxa= zJ)HTynk>{>M@GfO7F4nRF(NyVk|v81U~m4ehPx2_;Q^|V8nDiM zZ6sW98x;KorBOpCwz|4Z!zNuybtxq~WlDPcn)hdGpEBL|xP(E1I&bnwY5d!yegwi8 zN2hmo`AL^X!P`Ee*aY$IBr%JE9jHjG=^`I+pyOoZRHedg8w}GlXKMY{0*ENY_nhJs z#^Xziahy0`@0WaQwo1MR9E%3ewOz$Ey zQCG7eEPh2u-P_1x$J0P!#9YKF*?gewTUC&w8GFCBa@!`1g@fv|=loS6_AfBu4~gE1 zPapD(+jBO^f~C>1chp=D*IgxLyc=22t;{|6)_ESeWX5P4S7UUS-jZdS5FgM~Ia_5i{ zX(^w3%gi;*25lnx%36r^(hx+YUhtW_L;HkS8>Wz}t}^~Jp39-F&Dap6S)_1o3QI#l z?cj*%EjNR+^c$-d9?+d*@0LAdnRrY0I*&}!GX+_{^c8;h(`|A)a^)$CC|3CEj4LaB z;A9pGm|FDOpW1Vq3Xp#igKjLUrqJynZot(V&TaAQQ1``CTnhv!=qV}CXI=voO|ZY{ ztE2kBtoeO<8QCAFJA!ib>#q7tQV55Gt*H@BgR1$3rKQNvbg7H%2rBgVH(-(0(08XI z#uXJjADZJ_S;6f@mJGwl30uA8$KXDP*T7Vv52t@8(H5*8VI_@-1T%~F%)2sK+Ts?` zRn1fSQ+@4jqxFDewXlC(7VT%`X>PY{ zc0V5q-_{S|t^WO8g2DWl4BDAsd=htcf17gb-pnx*A%?bx*4w|&cDKX7X0})=P(Rj) zH=k(f@YB6mqlFn@EBSO^-+llQ^|DwpDlge_eL>9k@L;ZM1QR?$J|&zr%@vinAIq&I z2pM2qT``i|2$kG9Z6fxohb%jI^IjRuj){T8V=4omIE8rlyXocdFwd&(#}0Jvc~l{4 zH-)Q_-ey!#>KwdO&7&_dYc*m6!V>j0&xZ#}n!6{GEaYpUWg*|4mq`;e0%O0dIM=&` z6Uw0>lWrzmc8=~SM zuB;TYAPO+m?Ivi4p=UeQiMBq|dv!JQVBW zozUvya?ILrQz=DJDlIZX&%4rd^tlTjPc_> z4D9?v6`d6A8D=jh6v-8SeQ@?Vhrta{y<^UX3a&Xf`m;OradC7qi+ycm=niY7QGoz^ zq5^OA7i6{P`0jOQb$5>V8zQDk-&$~HQ3h&1^BzcS$<_zOv90V}H4jMx_YOqUK1V_! zvS^q`6)pmZ>oi3^$d{^)6nf^QCxQJw(EOttzWCLwMc&-7H!qKlX@DHZx+J^%#-H*vG>4iy=6^xZ0X6mYlj}yx5Iu|jeK28qu~av?9n^=GWXHKui4Y9In^!AGFe?! z+R3P`N((QA9H4-Pa9fS`QN5vknof3EJobx=9NVshr<6PD zSZVkE$zTp3oxV!?=cw!W#feC@+}B8IN0yQ^;>($_9Mt^n7Nu{SV#pl3n)wUF9qS)_CL=XHvMSqYh z>z||aPb3SP`djt~{Tcoy*gw&q`TvLPuN^w`NBcKI{W)>J_v#Gz5Bd}OztJXF^M4j% z%43iTOx12%ji5z;f4ZsG1aq|xTKcK^ns2Z9Da?%o&9Fvrr`6F=Z>M>$H{N=Bo4yH= zt`h&y;N01(AGxQw8%{?sduKm=i@URiv++}s>JTVRNzB@)PM0E~EZb{PFZiYV9oa<* zC_Jfa93c)wf2vw^15>KtV?-31a^S`zdzsHx5LdVW+ZV zP5+zyqxy^em*r2fKib!S%>Fq3@%o#!WBmvFZ$Sc4_J6DXC(Hj!x^&n-EBRj+_8+9P zOZZod{@;E0_jLbx+Z88BtgN}}Gp57j@S{-XvDt<=!7dU7K+0qhyU6o>)IgC)V$l#3lGm7Q<2|CwAu7*r(Ry{`F)j3V|kxy2LfkTkYf^B7&(VL&7RAyx^ zA5I$q`qh2j5@cR{^kI;s;wlQ8e^J9a32Tt@wfSnt{CBy!O&S+Ys^Ce8`xUiM^2$lT z*9!eymNG@P=?PC%8p64OzDGMpSo+}cRV^Ou%XTtr3l8nmjaPWT7R_(JV2 zD8F>1j|f~dXv=)0I@9hzy-BSEdZmuX%Flj&gD|$Bpy1N(rgX5seGFFGUGl*YKcHk(<6RZuA(mKD z(+D8`Jdw0%=8&P|R%+4%GuD~Su@6dRxp+AzV#LFQ)(`9X?Y-Csr%}#pQrKrUZK;@H zPx3SEY$t!nxsDXM)jA>3u^gB&J@G-Ru}w9HVeL~9K1-<9e60t<$n#32LdCX=q@x!d z8nvebylRz$Sk$4jR%lGqZHqqA!B58CQS#B|+uK>E!o4o0_P`PyIY&B**GbiNQE zn8i`p1Fv|^iEF~~QFGFyIfD%P)`tkxBVW_a8_EV1NegoU$RGHc+_j@ax!Xrws4N+F z@3Bqupzpts+;j{WSoOzuq53UxW|~?v`hflmiM_kk=?U%luc6!I;!2Ua!9hlx?n^UG z$F}>9g@FjAN!g_Cy#a6Y!wFI=xNy6_SFV76@KWXM6rS4}W5^%RIK1vUs_YKoT`ANo z7p89efKv5y8(Wb3Goncq#bH&o4S9#eZl~U*phg`l(Vk|Ut7yjpTVH|M&i!>T^Omww?-Kp4QariS+b7hooZC3_DP-;t=pnlz zam84=>1~_l1vq?7zUuLjv`--e!_nASrCds=XkkGCokW1^VPgC8r!M?G1QLhtZ@3+ABht4xOVPVh zs-!56?&-k|Rm|ipXQ6_bB>MspJ&*1Kfb-~&F<#|V?9Wf3&%=*Kd_KY9c*6>8MMYm9 zwkP!3P9XLg%QEr>gzzG{FgK-=Jnm6tba7adeEx%I+N^A2s`qAj`>|Yps+Sz}WB|Ejc^`q=z`la8?e%t=zmI=T{t|JOeXS_AUH1433-hO*~2+qgshD zHiI_q>O~wom5_(Ibsr6owk7?JYov&>%E+ER(S`s7Y%&4RE-2eMIuFJ`DMgjm9sqp` z=vV7|P-Q<1Q5QO~f>QSVN)${5?sA-@$XN`pb%{x?gc|n>kEO+WG#q?lxsvgW{xr*D zG})x6jWgP6^2*8_K`E4=Y#w~7u~CwVQO**$ow;x(xsrKPfiB)=&s}zN*~}+7Ani4x zwvpi?L%4IJoIk4(%W0C$j{NI&@5T>b4gyg=)1$>sWmE_=l+Cz5p}pNB>-XCk{OWTr zV)7LTvtXGE>&hSs3P`RkY)l_*`iHyjVo5`VX}O190+L~$12$5mnVIRVM(<$7PTry* z>}^vVP`e}TXW2W!w>ZKfk37KI9)m)BVjz6%eBvz*?_)%4^}74q*k-P8vkC-Q5iD6V z)O40~vGk`1xaWoR(%dR{NUNADtm97x9w6vB!%}2>kZ^H#2=2jyySux)TW|t|V8PwpEm$D9yKAs%p69Kas;TcA z`8{29b<>yI=Wt~2wbx!dQc2-6DiR?Q1Ox=Cw3N6C1OyZU1O#Lq0u=CMz}tfi0z!^S zT3kfU1M*~^!wp&lLt?Ji_uoJrkIBZ~mb_{BN=noISx?Kh{O`hMN*5=44^?6SCN z&|Eh%hr?k;y__aeGerQZ^^ZlhD!S}>qy$6hooZ4%#fkt3=MW6hD$Ny-%;{YYR^5BN zUhh=>4mde%GdMdsvKBL8ZRSPGF`PI2oyI=XLUZ-*NDY-F|sW;h|J;Jk6Y{L;eDG97kn(t@`4M;`?7bV!muJN zaJ?OG&S9d0!EH)fl0ypwDZ=-VV)4drcU8KKCMytnM!i$yj*BD7iR83m3WyQXWs8k| zIA*uxm0EMsN^_-aVbh<`a);qo$9b)aSukQnP95P#Go%*1%>_Zst;?*V?qdhMYZC0L z7_VW|R>9NCd9gVMpR#93v$^XBX9l;z18J%CYn({z(hai{lE8x*UDVYqF|&=J7~p<8 zn&QLWA5F54f06uT{kI}R35>_n1-;NGby0rrW$g2Ln?sTerJnfuho=et8G245?Hbq^ zqd{H+^_oaA{sj+=kB?Kajo@W`Q#MO7#n2pQ4P9#uO*@dN_0nrhRf9Bf+R-OxZJaqyLefYecHLE z?$g(clS^9j7E2ZD*y9FGf3L5viExlYzxRo5nV6dHZuW)0yu7%dtytD*u9RlZ%`YM{ zWNbMjM~Wbj3wD^4`S)h3S~A3!c;zW%VI??leVF3@Xk1oW%H#j~ywMXp6ieiOz9ygw zIRr{B$Y4cj(Kd4b@+Eam(hpIKK^U44OF_0j2!)p#&wzFed22Am@W^mmzu z%VxE;L6wsEYwH|8I3zq=$nO~x>V@*RqM{;;%U)eWgQ!wl0Y!s!c`{@de}Th<=LqSD zFi3Um4n|w9$E7a}HRku!lwt~l#xMTEGGSd^V$|8$+0~o$;Yo?#W%>E}kLn3SSG!}Y zAVt1VV1$PI$xfCVWFsh8Sd>0wj9m8zZscYUh3xch5g_jIu-RuF}UC1y(r7B9w8 zypsLn!RdRwbi=gI_5+4W4|ycD(CJ@F3XXyq6;io+rPp>W*RbOTqQ1Vq+41;+s;cTx z3;~;tX?-3l2figTV23lK|(^Jh4(c(DbTWDp()6e zUtL{&jwf~ewc6&6PQ(fH(3&+VA|j&3c*t(8{V`clP^-y~B(1%@{R@M}?eRJ~nP7S_ zJUS_l6HME@)z?NFf*li|AE)q0p`sLy@uNu2xeC`NIAs*@d2AUD}+;4er*ZvAQ zyc{OO7&oxUco-}?8Q=^hHSN@#V@-EDFu0@WXHglV^IT1b*KL`&IhfUdYIvC3zvm(6 z+{b*q)3>0Y;GjrI2^NXn;rYR_pw07oujAiQdG)|bi*wC*p3u5k-R9#q+1ta`Ky=sJ z%XvEU*N>~MMg95t`^cWFd$nf#un>SrOOR&KA)mP|5qdeiJziYZZw|%c^+o%5go}$S z`Rrq4l)%jJ(K`71m3_#P7&a2w050=-o(IDUX`*ibon&)Ievu3@J+Y(Aw`HRJLb?zz z6%~x{-$vVm@gZz%Y~^9-VcLkN3XJNg4-Mp4uqnFU%rE&54-eHwa##U+y1H_-x>LY3 z3>Vy;EE&(mg@6o{_g=f6R?n$~dapKmpc$*$ucDe`iFuO3s4$3IU61j`=SmdGSV3rD zP|VcJ5l=)>M=>%mF&a1lYFZi6_;`4=q8nzYx=|9}zI_vV98t{mKI4H}J^kAhOSgz+ z6j1Po#w3M#E&YMJl#Y(|Tu*H+$`=tQF{tpm#)c==i;__z+kT~ahTYg;l#Gl_5i1~( z39mM=>tA`-(eL81PyUZ%`Y%TsETB~CQTeK_*MIP2J^?y*cE23pW_Wmb2zFQ9*Qs9) z7b=OUX|y~`{G&u&Bxocge$s;zkWNLfkpY7(Yx$?aTBDKG zGHo|14I|iLrsJp2y0c}N99I`r4Z? z7BVAFRUD}R65>c`3aa> zJTjRzAKuE^R%Yf7leNx%)9_?6S{xbdUgmwBIx|!@uhM0<2`(Aw9r%M}TE!oBl(U|f zCH>+G0YT8AlsF%_DYA52X6Ok}$pqW|-(E#gZsiSH86s7%nr^;>`W^PqNNSO^CiLnp zFh>VtiKKfB7#En(NO*5f?ftV%Bg-|a91wmj*IQyE@r$G1j-moKTmUn;Vn)ysHELk7 zB~}=dulUJ*%`=?GQ8uFBN24R_EBE5Lm6?*vx2cw!qs-Qkwyi>&N!%fot7wK#Fgo|E zHE@!+xy^Pxs(+%tIC)r(BvB_(E0HWW8&d8v8IM3N=X;3>go|KzYNh0I+7c=XDP0@Z zK$6`cV$(=%M%)@^OLNfOve%s`Kt`b;?``-oE*#Wgy!g63B$y8~Rr}C6z&*m?1clD^ z3w7sVVecTKvV=LCPZ@sJZ*yZhjHY@22VNLiiZ~XG=`2|ai}OFY-DhDF6`xV*bh9t7 zM79x#851EG>_6Vz(yAJ(L@#v^Cbb=Dj$Z04?O-oFBdLVPmi+!*J4V&#U>s42x~TiR zz2pGcY%_LOa8YC}vE-vojBvjrYpm&*bc_?2_^&1KcTnYr#d4i66c@WvsdSQ+aSR?Z zaFUf{YIrrrUI;)(C}bBi_^SS;A5bHND;t$ z;mDu>w*^W@?`vuR8$+z|i(Yy6U*0a#2Ol=2do?~0@ZTjbr$4St=LNetiw&!vQTg3B zZPyEkN-Um`-N_Vh{R?jYHc}kPy@gf2l8EI8+eA>T8a3?h>EwATzaN2U0AE|p$OIUZPw!L(%&)eA0{->uQ z%8^BbSv$)_N1jW|`w1eg*v?rc@Y{4c1|VetxJ9yt8ivoPh5OQK?{8{;Nh6vHmC!qo zd?U?tA>v$%o*-ITX(5hlT;TK3^`El?>0rK(LLdayIpJ!jFW)DzPRH#qL;I*7sy3-+qs=-Cr)X4;}W>pr8osFPO65Uv|az< zY{{Z!EmZ@pq z^jGNlLJaCM8B0u363$)>6$xp}byh44WvR}5N@JoTIy#!q{Y+O$DIhmB6?WhE%UN$| zdRp3d`?Yo+z;}e&z=fWwPL=N%6%c>=ROP%sd8utXv@^fZ;eD@eWFhdrTqOGmcwG((KgWyj#}*QC*`;VmVGlq-LH&u1iZV*)xlLuz zh)^G20{lCps?7-JLY4lMZmvzhSJAcIv2=72UU3Zbd%#My@8%V%{0RiXp_8rz#q=1} zuqfaluCr+Q__Uv_wfaVrdvEn4CIyt0eZ0!$TJs3D38>rI*<+Jos%cimTMX@D7rgeAAQc(jVBG%=0x@?~3 z8`eveql|e|`sevt=&i1ZaZ2coUt=gC43$WdIu?ZL{qnpo6yCu->XMtOC@L!2<@Z7k zU8*#L$Pa1ga=d`*f8Qd)oOYdb*3CdqPd``ySa4Axx@tllkLY$(YDPwzn}Zn{luG#b z{V$691^EaU=CcdUs@zZdT3I!(r_(0Hp&itI7Yhh~I&uEU>Ja0UV%c=8#7l}^zk9y* z0uyxG@hq-*F)VmPobPwBSzO%6&L$u1^8|ghB~f535OV@VWH?FzAc(V7iqHe&e?{vb zRGd%le^6aOCqIN}j~O?>Z8i?-6+rTVC@$!Bqr&Ue!HDeJjEIeWxtUcQ5aQrS?HSt_ zYcwg+s&{?+h@u#V)Pn+I2_QYtih$HkA{M<$!laZ0^^;eokZPkNg{CD%%*=r^<_fV_ zz8SH_?_prS0YF^IhxP_rrLV8=TV*ocuoct52RfM0YCh9Z9GMRc8WmKnn76}Nc%Sqb zOUPXm@&sT0)EI||es^$n<-qy96$7+Gn4X>9ijjB&Kn+u>xdV+#ZP$wpk$)x}L0T=0 zq${nivYJuikWgZVD9JPmMYSOc;VJP-AQpUP>+L+BE5uR=_ByXyD|$!~dote}OjN}j zUTS2Pn7jlg!&P4+2&FjX&s%IMwZDO}-O8T>kWS_~wm zTz45q3MC@a2uw^w?`Sm!H1P<1h}yyQ3kMu`($vI8nE&$-nNs6c(c1<3n}OQ(&kbpL zl&DabTf}D00MP<>YRu`#Fd%>_T4VKl_Mo>8Kt1LHV9);ZVv6|4`s-a2R@cv# zsT@B1(A8W4Z1&L8KdsC!;O5;J38x>hvuvESw=A zlEy-^hC5K}&~&6w#Jbv^ocYFP?(|6J|6F4NnoD#$`9o2@zJu|;#2k|OerP692<1P+ zHaH-~TzS@7K-ykB_W2L48r5p|!ArGL8mEaNh4yYw?}IX+gnS+@7ACS*Y=Q^4`%Rwr zCbDocO~S^AwPz7;Zz$N3sQuDhsWyE zkQZHjo{1n^CMUOB_YBA-d5)&BlX?wu)G~*+e{34 zIpauz4<8_}3kH=Czqdq>adEL9+kO8QPY9AsE?Lq7 z9PW*IQyxYAtNlJbu!h6D{>PJ3{LQ3QouT>pS+0#HdPx;$@$*EuuC~eF81{O!|A3I5 zw5)Xi0ie9Q7VxEI2~_Z;F4`+n%g} z?S<%Kp*FCUM}H|6?Q1c9r>R{z#Czv5%lzqRMTRY9J7q5@lkLdaXCJ#C(D6k++{ z$~muYJ|!AI+(q>=7Y=vtsABdPXZc>NWJ=yL)pb=C{sTnNDTmS)=^0rK_l|t87s-yV+wn}__{f(@_)9rhPC&Ueg}>%g3^kL(b37%6uX+`lhDSM zAUEc3OK!4mc0at09RK!gNs7rv^Cq6o;zpNvvFOJ=sCE!$GCh}Le3j}SS2fY+IH-sF!Jy^Yg7I+ zzVtU1=YuV`+3eEk<3LCzni$F`Qj4d=5|3xg9Tf0t+$pJo`LsOaF%6>wP%o3_bA_Sl z7uR55eR*I#!VakGKqk-JDWGIBo9JB2%8Yegy*P&bJ`$>(+iJXBpC;ojJ0~ysX+Nuf zP?m1{^rl?e_%>O8WKWH$w?l29#p5;s;)MWT{4vyOxg50sAmatOfXV)!QkD7y(2fY3 zF}^^Rl3QLQ9e76=B~Cr##h=v~Jb#eQsfa)z%z2lLpDC-Dy`wPcOF~iwvhv zBpbC5vHf$ykH*0{rl)MB< zvihUf=4N}fGm2)A!RtFeYLv`%2I+U zpj?aCg68IoBFNB??oEfHk`i+h6VT@|lHJJ2NVhg$AfBW%8Xp~vijCbpB|2znX_1hS zFq)d2bmPs@H-l}Bjf~tpz+X*EHy#-oNn8a;HGsim0Q2_&ea2C`E6o-#UwcFjtf0d< z-o{cHMtp|4Q&U?oGtmwv3t4G(wx2(0sM{YOaPH|HNN3jHPNBjkyFK{!%~tFl{ZE_k zkb)lM<#pcM^Pfvq3Pa2yoM1TA#A1Y9=zF%XS#yP_hlhNCUh?1Q4$R`T^*U`>oXizq z`0|57ER0dB*5vVO_xT&$!|;h8z###IVXmMr?-Df148T5|7#bP^%-feQU*yj%@b&`K z4(?v=*M(dTFz^uG!D*Y@sgd{LZ)(OSyH)L0mr|@gHq=lv6s)svPuOr752^@8o&Fos zn5+=$gmeTVC_0U&8C?dLxz~H2xSj8yM#RNUPV#%iRA%co&^1lctNdlO%>dGip22px z);3+gJGGq4fRH+j_CpweBJEaNaZLeVI}}GE78w>?4G_{$b>0e7tXO1$HOQ83~_TzS1tON?}n^(L1A3 zxC0|uLB?qV>c=1;cqDtfBs*TH)B(mYoXoG;eqAsQplYx8{{nl4~AJ5|}$^f534oA<7Sv%nQaIuLY2EhIEwT_nP$X&>+33U~f58_vK zc`q^AO0M#;j`mnN&{};4n*{*-NKS6B)gP(p-p!R|`lmF^^OK-@inr)A=G!Q*<+L?p;qLNNob%cP7gJW(q&EGz}OPAUgZl znSA)C-|RpEK>EWs=P7|9faB|W0|FVsPMC;rm%z4osn4zM=L&sHI*ksJtcVDacBYqF z=Q1jE0fLVwNQy5uGY3w951e4C=lIajJW#5h4MRC0^flb5b-Nj{DANdk&OEiv$U*deucsrrb4VBq(XLfQs;a56N z>$GW!2PsqMuT;bJw3#um+V#oeyE_%owGDGoo4cTQdgg*lR0oJet8Y9>VS`oPy zwb&Hx-RCPJq$p{s85JRugn`)Y^MCBfoY?44xw-rBZ<7yl;(M37TlkliR5t}9H+gT! z?zVJ=emyyrJ~=fRU)f1AW=IH_O^gs}5dm!WK;id(1Ard|4r;jn=S!HmR8;fVh8TE7 zHQ?ZK2z}x*^P|u5^yz(L>53J$W4+}RJ4EB13)W( zSZ1bnIg@^K!B^~H8N=bQ3Tt4afDej?=H@zz60ZK`kpDJ!jIY6Cb-OE!--h`A4v{U8`G zRb-uHi5RA8e(e5fs&=pXGw~@qQVI7i#bWr--kdjXx4)ENj9KjD*|?OHYdl2;qJ`}!)V&kA54GU&aSE|?Yl)8A}CmSUjbfy3sr>MxCdS&(J_Um ztcd4xO-h=EQKBHS(0vbGT7{gY##LGx=Ex{j zHJ9fSXgD*SQ({za;ts=YGySerddqL@`vkwnH0&yF_564KNK4cI`r76DGMFRajlPj= zIMNfukAk>f?|FPj(uS3!LI8&fjFS5!oIzwvoH4$%l-z2q?a;!hpd;c)FY3CDQNp>5 z-e7S5Q`T%Rv`XJ|GMQadF^tes(?o2(O-lUPS_hx!m5FL{W+q`{XlST?=i?rbrd00a zOcwUs&v6eiCKd8Kap8?E1Wdv0~PjhiwSSo98 z8)BKXG{vZd{5yB622sk`Gzve$o$;YM+W!f7;BdOFgbc{0iSQc_#l2k=#t%!FO?~6C zx&irYB%uo(Io_`YuX^9#AI_$O9Z;d+P?p^{Fed!(>he^#gVe&%h#cuJj#{qMfjhgA zS{cc!SlY0DgS?yJ`>5-E+#NZF(Hs)@{f6;BrJbB=F~o>WP(G*}QT)*F^a?%{YLliv zEP^dP)cPEs^IQ~n9k&|4nujgxjmW}rJ}1do5*A_6t%NsMiI&Pzn#};vR_xo13)B@vi=4( z9t?s-z6im^W7ZwU|9TY+kdXy3WI}?RoOchG+x}NCLf?3tY2F|P58qiR8mnhA5xAm_ zXKXMnG8!5)9i0PD=!eHwRxr!)_ey%%gh%3Q{&=@}X$$Fb=&818Z=Y@tC8^C5Zk$c=>7hI(;ylA)D0`YGhh-w6R8u=0OYg_$Z!X{px z&;dNVIcGV$KcW9XcLV;+v(1$YQXxH6hz4mIe6?yCZ!({pn$puX(N{6Z(X+_{5`LJ~f{9yWn(IOd}$#8_j>)rN$llZm2ZVq!iQYE^Rf6?hsY>;YL#0KpsWPE|)I zM&^SYy+`|5Oh@Y_jeZ7#=&o4&OOE+O?&;4R*p8XIAkv7fjx+-u?k8||TkkZv_b)iRUb~*eF@Z1l}(iQM9mz6qAnGu1E zsWt&xLjQn#fqJEOs6zhGHNXi1$%&J>QtVe4cTlgCH^2!F%>VYLILr z5buOHJz}UXjKnN#Xzu`$k=|OcWa6WR4J@F}CK z4^k~0%I(~^!QkJG){WcIP0OPGxu^r}jr~e}>ZCGY1qQZynlG_OKK}gtwaf7-RUe>> z>ddAJ_8&rUTE9yTl%f;!{;tzFFWPa*2)MPy`&nwCe7GfE`}&Mxg5q64znwiPze{aR zY`PZryCF{H+^Ny@cuZDfXq8}#u91KM`Z^BC27uVB-Ou$R43}z6!z5VYS_&c#+kN(d z1S+jHx(Ns;% zKhAx-W>lDl#=^owtlG%S(vV`$=VxIy+WFQ9B?^MPmG?)yUtnCL7xU%{$T~8okgd?L;9eTs>^WcDE zrxDuTQiJOYMBTL(B4Ir(O7E#CEhWu)a{NTG>d;6K4ifB4c1CVSMuaF+`k~Mp$xpdL z8wymJ+wsu3g_7~bD*f;f(V)wY`t~SwkI~W*(4RCePb3FaZ7lQc_?2EoZF z`P9@bh8+KtveC-a$=FK~%F$>WI50-PzTcy1T0|*YP32=YQ%0jIq0!hC#7N+(-6sne zBz;CLAG3yUyO93={#sp`Z02azSlF}*?S3!3c%%8&i@ziwOBD0=7QV1TJ4FCHZWO6M z01{e?Tr&~S2yo$H;Tuw(Ih@WE!as&M1@{KvB{r8ps~b#Gjqujd**zN1&2T1ZxBSw&Ts9b`gsSsf+BotL!Zc0<9V&P|kKHnf-^Tz-@a!2PEDP@*hzpJ| zolzXPj2&Xp0GbbLx`Gajkh`G~X(Ao)3^9zxjVRT#wtJEK2rp(tjo(_ONYbs zMjf-@-z{GZjR~C}GTWZfWnyQNX@km6hZA*&`p5xE4Mz=kzq!!g^$T-~2K7JOB$^Zo z*01+Gc%+E_sn&v^{%I*drO)S9e)ebs2vQ!s0OVFzSCEAx zmIidJPgio$6U-SIJVC@K2I7O<64H&(3di>+WklL_k@;F@RyK@0cYl_ zu6~f#itX`LG7ct4a>M8uYVpnP*K12=T?X2>Njec4Hl4@e3v ziKV)MXHqL0|KY41qe1T>otj$8f3N>@S)u%IRQP{JhaF&P;Oi2R1>4F{I%_88b>8Cd zUpslE4gt6;v_7Pk*sdtUI(!e&_s34B{M%{qbYK^hP54TK(9zK{I7J`?r@Oj}u4sgM zsVqWE_%Aa(D)1us9`xFy?+Sc7XZu$kCx>L0sC zP60X)`kg5va6|9tCsOPE#sI#4yW_E)w&VgpI0O9c2gjD8iX_liwJkcPs+2Vfl$)UM zPCxGGhNohwE-WxYBE#6ee*lDd(atQHU|K&b()@lm=pxx6(CTs znYeb$sgT9FeKk*nW`5e2Z~;V-50B>sO?CUsaIiwU?IugvE!TaN->Gl(n_Wz=QY?}2 znByX%T-E2lBDEipRWF*CtPd+2|5|VFTYVwovh~~y#s8s@g$WRQJO34nRLY>l&bobW z%Rf_XKNwH`@HK-HaV2j@z^}G{v@mJDt0`MG{7H+U`Hc5$4#9 zwD@h`1q231%Y5{Caeu2)$RQ2o7j&n%c-+_Dz*zO0E2Jf9)N0Lt*RcSyfiZKl{k!9P z`Wa#)^3E|)_5os=CkJ6$UolhHzE;#MG*Vufle6_VRf}NNv$Z<^Tf+0!Fu0%`jdi~Y zRADOi(lSeOq6}77ulIlg^Z4oZEyXUKS*K^_a{;EtueAW7q@-B@Zq)V-;gd~Dp(9FL zUJT`nhvSS%B=-)0 zb9;mK(aUe%F!Ty8xS@ zUE{=oDMZ6r^La`ywqL2sIlb$?6;%`kNE1uz`dr0kxdR)Dv7g1Sx4(RmFp`45EIu7y z5T_yxos7r7=ey@Me$6Wixca$U#qA3v_~z)=(MA_*5EeNdK%N22f($rF5?PqRJ*fQ^ zLy2JbU{Z{GdiaqmXlv+uvXI*60HU`3`<)aNdM;Cwy&`jyWRs0Z@S>iSe57_Ve`!FH zZ3DhcvRWn%_Q7E+_1Sc_)DrbuK6a~7I;l+yYldyVO$?l+-Jdm9u~N=4wdy?`l13tii*qo@Umfvq3gLmDzI~z*B$9Uw6pAG_Tax+a z{mCr4;LZQ;RD#2m9HIN-Nob#ErnY8TUA|f26T-sAvNRI1OjkT)T0(1Yln}iK;FShE z1w3D-T3(R$^+k}Or*m0Ah7hlCh8S=V|LZd>3?f7X^uIlqG2jd#{#U1kFen7_e{&X4 z{BIijPbUIs{&x)${;wMPpJxvrp#xYD#JD_-fbJ-wyu7kxPgXc3tVg#t>khRGRjjCX zF@h)nde7VxEtFgxvkR%hli87d89+N?96>F3sQXsBJ&( zJV}3QU6E1fa=r8%M1c~I6IN2o^m5k$4%l`)QGdC%dxJ2X4zpWL_j4zfG>)+Z_px+# zlDt;QEVb+UBO~^`2y#6i%M=1SeY=j9SK1_&6>p*#@Q*{ePB+0n<-uHj39(jAR-_kz!2nc5d9DVAP5X-i2vJ%|F8b&|MI&353m29ZwfR1-*)2v z^8Ww+5C6aKnbiOHF$3ES)tzxc^wBI!$kU`@@7@Y+(d~TYnPT(NFj4m^PIE z>>-HbC1A}@;bA(U&{5DdV=FsFcOO22PRNfT&IrwiBGSM-f~GSrH{E3>zNcuOo}vYd zdqAAXDE~0xp1e-&s1Pa{*o>f+h9nmEM-R3kHzvU(mtKg?JUmnG_X##3EIl*L*f~qn z24$0ZQ6Q86s@Wa%Len)-u*pF{FqNat=8!_LL0uX=?lWe<`-|mQoUJNB(#Xa zb0vO=tGRFPqmI&L^Z%6h@u(rSc^@hNneabk3%5M*yP%UJtkno~SewzqxmO zJWu_6ni`3R-tZ4e7Af8Kr~k3L7ZJ1!oEmt3ryZeNx7{KMfy_1Ea{1m4b|67=M5XFo(k7rytI_CAtfnun3~a9 zu@125c`BDO`YJHoP7cj3n~iA+(eF8d+$scF)^jcsLW!>3SW`<@5eJ zv=a8Sy@MM_)bx|Y@H*q>)5a1yw2>a-aPM23F)otz1(i>qO_x7nH^K9ICB_@e3V1(y z-h!1(aesTn+Ll)*JLfhQQGlBp>uui6!2>6>m$w6HXo!}(On>CZ^^A$1V{!ebgCbK^QB!{N*jn3f*)x% z7X+TQ-aWHD56sx)T(kz;FsOPf-!UtLO0 zI;YWKs4b^b@Z9Luu*CBmfAq9aK|Rl{@n37(>7eg^?%}anph(Ajzy^XJX-2vf|EM?V ztG1eyg7mIP;dy(%wW**N3TJ+9`{kefs!9;u=^S#eJ*m-4@Ee9JoengI=G31cTT zG8zQ0C?{c1%YKuxK+Hu`r5{`BxI-jtXqpF5#&fxIlwyi!dd(cbU+LmC_w8FZE%fbkk!-2#e}NDy6j2Z-q=7&YeT0O={8w693W$R3r}G1ige9W! zfFvF&x<*I1S>Pt^Y`KM)25OcV7!hb(<0+BDqZH=wA5|@ogYhMGFJPo2Op+SfB1_EmBnJ&!ejQReOR}0 z$CtXB+_+om;^u}wO$^8;OpcGU2RkU{l{^b=;zNb05E=--rkxqG^_ulPTH7t2dwlIU z^*n7{#OCD(MImNFnckdAcu+ ziH*$xv@#s7#|y=}4OXc$TD&X=MbN?A2J>c;aZC7ELBqQm5GYm#zsJfgXMeOG(&bNN zas)pf6vn^H0zUsN>|v+}U69Woo-4Jt$y=DLBv+JRf)U3_6PRcOd6+LdZ(97O2#S~3 z3CrD}srfl%jtOM?=xxYcGvPg?go6Yl6@PMHzQsT)$~N-CqN0ep0bCPHgVp@Mle#Gg zxCcPikj>+~S6=RIJCu0hXH5tDL`P3Mc0fzWyQ@THNacXL6_iupzR#j1{ zrt-Q!t27z}xbq!G5|GR9K#|nF?V0m=IC z@Nhm2J-y{*HV;sl_FJ+%vYaFAQ=7Iim}Qt6$U=@GpY7~~@FL`jgm40B2ASPN%FoWe zZHPXA4Bs6P%nwHawSEn;ZaaI{I|N2K)z)AZcES_gnsgF5Ny)v*LX8yGZJC?;Cq?sP zBZ1SD#yXuC&5SF?y;jTh7DZki4uTUD(rHp1$i3i6b%w^A=Iu@Yv&<)pHhGyRE$$rd z5Y!o?4CMCu6d7_za!dYxExFhqVqb^(j38hUP_8VXprIcHKC1n^I4sG-QVuZWqM`~B z6YlkYz0L!48UD|gL)~z6DZ zz-xEHeH;G^I#{7~fP5UN#;9A*35K7)gTFg3*#k)8mhVua4uFtG%8=1dtsB?`(VSsU zlA1HMyS9HCAV52=aLFKGAzC+RY~pc;i2o*J2ekUxoVLqA;Q}CP3J%32CT6r9j~~U6 z)7H_Uj5d+NgA7*PU3263w=5(#_Q&nu`*%REkyBisk^6NaL#ad2t;0pO>@0p8Z`;Kx zlX6MgW1y@4zQ5t(pnu|Nl7!n;fQDkgb0Tp4jRoFW#FB@EC;MTG zr9Xk#Ez`)5(3QIqX5HN7)Ne{TQ$=pvR&#XIvP3q*SLDPY>&=eafX+R%%W)gd&YU#j zaQAC|;qWv32!Jhc*kE%amUtaQ0#;FF}+d+pOpSeD=rG`!8-ZsVWRPn7ubdClZv zFP?e9{aSX!vN>S$-CY(i*NN4;8rPRr_=xa!Dr$sJ-j z!hvBKwv8r>%mbDxQo~Ss33xEp-Bgo0`uric&IQ z?2D3qmjlkju7Or9*}F1Ll%Y>66ofS{*E0*0_;egJ>ZisUMQszPO#wu|{FtrL2dD)! zJ8zq>URE;tpU}$h80=9?Ubo~w6)zN(yZe4xztV2p)s!-MKA~=t^69NqEAj7vfL{8! zR4QUR_TeRQ5y8}L1h4xI;d+ENkG!XbNZg0ZZiQQ@Ti6OaXM^v%B6D~$QbN9@pVMo; zQ5%G^O8h4kc(@!F0}sFAsgho9ZtjQ@(lt4C2D@Z{?<1fNhC+vc=4e0s+UAxjqsPV0 z1{#M7fIN&jFmc1=h{pdUSzSBU|AUaj3I+y7D*V%qjL~nbz!0EJ5h#9!`z+z*MW`N; zBnBlFBpm@811fxlM6dlTl2RZR-rC$e9Z+~s8i6K)pd>$tXd`vyYhgh*4pfl1pDt5x zo^?I%ehT<-Ki}c)4x0a2ivpt4@>0a(O(CMin4qD(67DxTu!BIk3E(>@|FysuuZtEJ z5gjEf=O;R} zk0GWn|9Drfk(_SPK5(S*V8fb%FYd9TA*Ey6C7J7v&(EiV`%-Vt{ojbBAV3cdKlcy! z;Xy2L)VV#O39n8}empZc8|CWdVSl5JM=3NkH2&jkdJYnfM6_#+V0Qso++3k{G44*c zYLPYyP-+^_N|tym;>CNKI4lKWNrsQV*krG-yr%pUvma0$BuRZTgP-YnFF(rwLl;rN zSwgZH{R3I9xX;GQ$eTkR$RtvnM1>$Yn=tXtJ;_LSLeJVDT|W5K~Fzu8ckf2 zNXFz_NX!GCK{qumg^`1fz$%mh0xGKa+sl28=&&zTIE$+I?j~)D?iVWv3ZZfaPdTm2w6;% zgK${;e_3qRhXdl^5um=LSnDWQO`-lzYKVQ*4jn<+-9ok6^uLB&uy~gyu84?;Nqw}} za;vK~RjLcxk%26x4Tc8% zS8pkE(jDxF0k${}idlKvJ2i_&N1>d)nnsQ0B`CEG`lZs6SH- zi84_H3KF81gWn6(+nW#TXz+u(dW^D>kwKbCx)IwRtGgSQnok`em+%NtrY<_Jo8C)3 zNr9II)Vb;L=*gE5a73{}KewU6#i0)=PX>?dM7F!Uw4|jg{Qz;%6v0NY8HJnp?F13oYVOc3s3m4_V&6Y1mmA*W$X?c!eAV7Z*T8*X`=;~ zqdDn8dKv@|h{nXjxYU3{VbsJVpb(FuxzT1VC@{57%9-XH2h{@<#bYFxJcxRb-1;K6 zaaCAdCDKlvgqAT?#}Cg~Q@bK7RuhFP_qDu_e>|xApdXsHDyL;t8520kN6AhppOE;-p(47@303tNv&LJE%%noRD`@|7Gwz~v}vBtyjiQQShp zT2c^-X(MVUa+F>Zt9cI)WYF4*&kQnC#KnRyziUY^55to(!O4X{Gm&=TNuq4&p>kR< zVSN}!5%yTdMiT+a4r2Zv0hk77`S(Q*l7uB7GFG@3@?6vrhJ}UUu;N}M3k$-|z*Bl z?TURTF5WqP`QD6$+xdEk3 zf26=WC} zgl7x|lCEkr>x85(`JHg)kaz$dh>VtGBs2)MaXx`TCTdF0fBXC2m{!f?c-%*S`qQ5b z15-LM=%fQfUgVwZn(t7%Rua7SsQLC%1HF{BlAwr)h&wri(rMn^q@9DU9jEz`Yishe zRuW>md{5hMQ&w!*e{R>|3p);;-+u7?-eZ^c9lH#}?#{y(V6X!K6~hS!VmGi#5>aSu z4lD`eJ93{)R(PqwB9Zn$0yTz_xfgrwOK%_1(AB3!DwOM|E z!EhHV5^q(dij~xBRjFEq;5G=Pudb?-8PZo*HFMT4OcnrxnbC@bc|BHF?Vl~REB3M_ zUr1>@6)m0;m7h&^rNkqIG=GW9-(!FbzsJCCq5U2Mi&BXGZX|{ADYYIkzs-mRxo)jTED%&E z?B8SHN6Hct%*2mmO8Wn=FSv!|3JeM6zu=aYrGLRqC!NfF!7bu7_=4L{>KEKRbNhmu z*Uw*YE9CF1iUC?+K<3~zl7;Pzefs@#|AL#k2`be21%Uzd`m&4l3w*(id*q|6@^${F zM#iau7wD;m)NDB^4I9hpe9|xVVY(48kblbuRMlNMYQ$(Sr#4mxC_H;|C_FMQC^Sk3 z2A$q`V2F-M;KS*%Z0sw3L-6cpOWs1e;bm$u zY<|(M))O5!=gDG_JLD6x?%qK#FOfo|PtCP}iW_&memsO6Bnl2Rc^oYhP%$YJKf% z^mC}%+fJ!A@$5Bs^)Ac-gG%7xZC76ppCEVdzhfEQCdFu77#MC>hOj(V``=X;(El(q zXQ-@JjdDT?v+Z}!H8Z{m`sH=8{>KIb^Zx$nT;O2j;{1h%@P6niQ9nG|wftWEeg}XQ zWP{Y@Qhiq6oD1?P!X7?8zZUnL8+hB>%c765VQSpeu4`u6^}1-(ID1CWv$fiN(;Dl! z-Rpa@4u;!v*YD4zFcko@0b7x%TiNZQ87IGD(4WcBj{b|D?5&~QooUVj0Emw4dBR1l zKZT|f<}Bl^)lc0PI(x%USmIG*(g`ac3x0*2!GQ8L000151Vf|MoA&|$0FY8v{(z*_ ziwdQ>bpcTc006+cP$<=-Y@y1HZf`goO$VdN@Zaerj-)=mf)GLohl>`~Uv9P++_5K8 zmzHjCR4COs6rx}ZX4Fz=2WIwMxO>3 z2OFC4O}naWktPeBxJpb$DgzN7bB~xq)OFO}hyhou!36?R)SdhUP%7XcO;9MZT12oT)ey=iE?aS85DLvXjorE!^j zGvD0%-nHh=pCh}fo-M0(tyTM+3R6*%!FW&d{>6(I7;>_bYA;^Ag1>n2G8^snKZzX) zhV8!>dKCqL)bsPRs72)C0 zvbs^Ml-nEGIh@kJ(X*QSE&b%=q}I9uUOrV}0JgBO7@b`!l+7B;9`5jK*3r>{XcTU2 zY{b!oIXk;Fxz@qDr;Ut^Y@@o|+}yrd$E4TJ+1uOy${V+_0Z!(Rs=B6db8}CFCzOWC7AO$?MD1@TQA}vBBPJXDO?9vq<*^;iOC2byCT_0I`1I`G?@m8hY%@jK za&LKiHJXi@Ff$lgedi&BU~FoVTgq76%4yNASzIi|Q7*n1O!iKpvm8##VlAn6 z?(uENCJy=RZP32ic0SB$;kp^qZ+YbpZ1!i7M=r!4r5%QC-e@|bE-fwjJbn-Svnif$ zsK3;wZpN9mfM@+uF{O{JDv7_AiH~bJ`lR~gWZjo1YrJIomMP?OPF9K$p_#)-Tn9?5 zlOKL};^Ht-?X}_RQ5*g7OP;ikwcF;Vu^ou0JgG}@1L_=J#`F)!;DfP$vchKajW~#3O&j`M5;pc1yJ69;e~Pw zH3L|}jbgCWRbVu<$CudoeHc2$ZB!L#cQU6c-A6}QSX3C=ZfAgTpMUsRYgr?lWiIkd zMiYyI&0~v~`c8_HvQLc(ZSwJt&{&y~-Xli2pP#Ppq64mPzMxbB{kzJk9#_S9Irf3& zyc8~Fp&SaGqe-eYA!>n(t-UyV5WRYOV=9b>sL$U5*6}ed`LfN|4sMYo0)UUZ~W)xY}eOIjSv`~u3-|ZyLqY!^0a9F)r z8LrmTXX&dlB6Gn#;PJMH6{Qt7&Hu@mS|C-|&_?RJ-_rtzBJa!XMw|x3|5^)gVW%hL zF6b>I#3^A#>QR~YW$N?SpF)6JU8nif{kj3O5y97|@mf~IIutq>ab88H+%I%pEkN1C zzG7RZWcQrO-4iLzyehx%Hu(TOmmzA0(48urYR+Fc*>+{S`x7#axUs|1z#IXF&`_W1 zz2$;}UJL0+qB7RzJL!E(iTwrwjks)_VcUF>PqA{6->O7@w?N^a-O%6eWF#W`HHmEh z1qNEtO3OHS8zN!Ut)-f^`fG3p&~@Tv*Fj`)sVP`;KZ8>0zy zWeOADK`mpwYxFFP{biR4-#J4!pE2ZjVla^SVb!aGrjDt&EZ{a>WGc*c=(La?5;px- z^2gh4300I|AQfT89Z%LT)zWO1pr*Zfo4k*FbQ)TPsAao-&L_p}#;{r)VFyO-M-7bu z*9dDs@Iz=K#2Kg-rNYR4QIIf8$ZbL;U{2%pl#9qv$@&(B8cwbm7opSUM^ge*+h!Ow z;>7m$vx6b)JnQ$ScOtG@J!hRhQTvl<;P>Xh=db1k_rsbG-UPlRy#0E+G}2Hm9sAsP ztylK7j--jFtmI=EP92H(lXcl9lXes_nv2GgQi(A)H_nz@ zKz%L4C`}q`?!a6)+PQzVSC}TvoF(#u8Ta{|9@Kxq_It^5JyBW6vT>Ze4pc@w)^{r8 zyq46Cb?1J=2`eBe#J(5us6C_rBi|Z%FmKkumPAd7p?rgs=<%akTjkK%C_%_LUk7RW zQ(}=EbLT8s?{Qf*{7scw2OZ_{x=($yJoWvYR9HMR)8C&!5Y?X%G`z07(vv~(=>&Il zE2_b;{}(sD*0GTt($38sq!Cy(H7$EA(NoZMrSS{uGxw>~IMBR3BM`o^1kB;fv%={| zGRK3mCZz17>e1B)-+*MY1-byMB)>*zcC>cAf3kh*VP}-{rR0g>_@w&ARg4_xw#&rt z%Ga%&(Rg==K1)e5C1Q%cZs%8$HFDJfxlV>=OQyob;Q28Gl#K!7z3I{RhL+S;Ulfe# zHC&RHbrxoR8?6W*n)26f(OvdXw3bp#iZmhMKDCFsq4=E6_RdSF*ScT=(Z50^Du)x{ z8~_Ufj6AI_GA^5PONO7Gm+$?OjT(dGp@0NvQ9TA8RJyD~&;B;+-C1H>uKZ@#Xvpt@ zSdVPHBpzn7_-g$RZ+-iLE#*taLkGW{lrG2SX5)Wz#)!FDe@b7ncZr`7a75M#DUQOx zOLQDHaPAmN9RtgrgONJ?eJa^0-1+S^|Kx%LarJ>rF?pCLzcsh6?{Bz+g!+6^G4Bj$ z--=3i3ZXbZTVxz8r$$j<@R$wHSJ*~7+L}dhYaa#eGie_kmWQxP`u=ISy`|luGp9>0 zX!wj%iX1uKlQ>1Mfh^E5B8BtEy z2s}1}2~r9Da(ev9Oaxsy>Gxa@uYybNqZ<-qiYtXSj#VM-E4#^{yhy|H)G ztb`R3oR0u;6D!uT5-KH<|3p@GT8#7|BQzby7v9)2s+(4GT#n-7Y7k;iV@X&_sfB(h zOkUzCa!!VSw=Sl|HB436XqJ@!m4t>XFOxOpx+v=_X-Jxi(EB{D9Ns-%_mYkTU2l&1 zWss3Aoig)2_8dcToonhB9BuxG*;_m&(3~y*h}OsfZoC^Qrn>}X&eJK8p0EEBmgK4d zT6J{gkqxS_NJssdTh#Kl?7`+$dPO$U*yhfAy2cGF$YXb5r@j7IHjIdV5^>Lbuw0nd zXgZ1TKCBJ>m)n7w&oOPTCQA4^-KXxkya8c?DbPHWye${5m*R9TIL^PYwnVa1$PW;N5dV@ zNU+~?kK3hfp)QqZNn`i3@9pDo!5uAb@mwMAiAYy}TSLr#x2Q&rN{7gm$3?(C!T!7?TUSb zE3ii+Vj_XXbK=PL^;LP;K!Rwhg{jwDNDN|V5fxl7?YZ`i_d_k)OI}H-7fQ2le(x#l z$Fi54YB2 zAVpKM;gau5=OeGQ<4GGsGLcm^M0(P zQv8&C|0gDO+XjNb^U+78+i}Hu+tlp&GSRv|ES2R1Z)4b}kJ@VSE;{<2oLYU(86>rb zd5-<-ytd=&uhaxaSqr_eV`ax=)imY1_`c@b!)OfV?qBpni=k+L;P&=QC{uMv8Y<-U zy%tddq7Hk-T>$mQa8ftR%(|W{GpOD4K!QbRR%T?F(Vh9LC&8 z(7i2sUGUVG(A*3Oja5y267UCS8pBTcU0+`6nb+RSR7&7Nn5i*LViBUdDr)?Iy8Rl;r+W6 z&EH?YBNcvzC|bT(q9!KNCViH*84c=c(^fwtU3 z0(3m+B34RoLrwRtGe&&wBmUU3C3d0i3;;&}!*A);Q|r9w7g9+0;J4?>`Z7(?k}KwP z?fkUIGiQkcz$RHdw6xi8mNGhK{l^ljl(6CD{ILaKbvoNE|L8GRjGF()5<0poGI%L? z#L0IRNU9^)W!BFM57@k4H2-vKFHxspe!&bVe` z{iaZkFns{d$ER&wyBtgsJsEbZzLy%9yC4V=bmEeBbo`d3)~2Ou@D+}^*b<4jS0mg- z-$sSVQT00`eg#_)&^4v@CCF9vNk|F3qFp0NM1%>Y;V&95XAGRvCQiK&Dr}B5Od0>?Y9@Ge@9Q$)j2z!ZgS5us}33YvFx} zm1}wS;w$On5P|M*mxy_6t*a!1%@EZ`s|7;2x+^kk8I*2g$G8?b>k?%*JUA zii8>%DF@9|QWbxXJlS4m<~|_svi%!~eMiQGq(eTv@|-!u`eO4T1NsR~CebMMUtY@oOn{Q9kex=8ecF-@LmIB%-zhCV=N{Lf12X_QcD_=Jc5?(r(m) z^o1CUk}TKR=x*>+*nI$(GG(r=)oqaKs2A^-FOam3fycaqqva(-Etsh$Mwx9NPf&4umes*rtzQNR>D7TR%21KNJ9qoWr*~AB=Qc zsG{_n-vpp55r(Ym=07&H2)}z^!E(13zOwI+C9(bP9|iE|Ac}InIDH35&{v9-JTK zzznb>8=kWPCknxur9CyL>9{~RrSG^HW1NS#{?MhbL&Y!By}X$EgJMeOY)Ib_CRGmA z9AMKQ9v=01J?EOqV$$>r;kjDYq=pHxR#zn_ktW1^sM})c zUw9%(wW_13&&|{VFz3Ld`_M5oRPCLu7ltJ46BXEhBf2-GHoMhbKpzFg!j~et`Tl}* z-w;VNUGGW*Z#5cMR5*T@}rne=w7J8UL~p%?Ng*|FeL=) z(7Xz9!^*)|%USkxgz$wRn6ki&w!vl>IKD@Jo~5PCGO%%#j3AS|R4Qz)0mP{ZH|KPk zG(k+!wn4Dg%#&3WUq$%=Tzj7}1Db0s*H^=%@bIN;-~th$SrpkPxU>{ZFcwuQJ=TH3 zu~ak8Ivwg*%Cp~4`lO)&mxf9(kh?{1(W(1#2~PjmW&*TGujvoqSOOzw1tC%ONyVD! ze8R+~N@R0rHYhQBRRQ6MicB3p+JHtKYE`WZ`L*jNI4FLw+bOTt%$TQaj(ZB7S(DljJANr9Ee08+GbtBn)aiRhfg&^MXVa zQgN)&TCt0-7wO%vc5t(CXgOJx<5GST+33nuHc8|0`tt6NTtAa}W1=m@q$!M#9Vyal znogVQ%x-FxDDCIG7E=2(F{PQs3f+dH)LJzs6xmV_$#R$3(dn3^o$1EkqGO7}PyrjIt{tnwGe(zaib#$Yqv{DkzaM&)b9j&%*lB$MH`TkZ1p-_Q*xL z#~%QrDLMmidm%cU2*SRPfFKc3wXxz6_U zksHmA5#GT#y9Nb(HTBhTH@cNZx)?RxA`WVcb4xv*5-4}`ey2B@{O;-qirGE%ym*t} z!Hedczs(u0|A;L$`GBFKnxK9?h44BnYDBN=U6oV$;#GJm%o$hQip;l7<*}Ptq^

  • uWtnP|{6s(gthjZwAjSRUhs( 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
    {headerGroups.map((headerGroup, hi) => (
    - {headerGroup.headers.map((column, ci) => ( -
    -
    - {column.render('Header')} - - {column.isSorted ? sortIcon(column.isSortedDesc) : ''} - + {headerGroup.headers.map((column, ci) => { + let {modeSupported} = column.field ? getFieldMetaData(column.field, schemaRef.current, {}, viewHelperProps) : {modeSupported: true}; + return( modeSupported && +
    +
    + {column.render('Header')} + + {column.isSorted ? sortIcon(column.isSortedDesc) : ''} + +
    + {!column.disableResizing && +
    }
    - {!column.disableResizing && -
    } -
    - ))} + ); + })}
    ))}
    @@ -165,9 +172,11 @@ function DataTableHeader({headerGroups}) { DataTableHeader.propTypes = { headerGroups: PropTypes.array.isRequired, + viewHelperProps: PropTypes.object.isRequired, + schema: CustomPropTypes.schemaUI.isRequired, }; -function DataTableRow({index, row, totalRows, isResizing, isHovered, schema, schemaRef, accessPath, moveRow, setHoverIndex}) { +function DataTableRow({index, row, totalRows, isResizing, isHovered, schema, schemaRef, accessPath, moveRow, setHoverIndex, viewHelperProps}) { const classes = useStyles(); const [key, setKey] = useState(false); const depListener = useContext(DepListenerContext); @@ -282,13 +291,16 @@ function DataTableRow({index, row, totalRows, isResizing, isHovered, schema, sch > {row.cells.map((cell, ci) => { let classNames = [classes.tableCell]; + + let {modeSupported} = cell.column.field? getFieldMetaData(cell.column.field, schemaRef.current, {}, viewHelperProps) : {modeSupported: true}; + if(typeof(cell.column.id) == 'string' && cell.column.id.startsWith('btn-')) { classNames.push(classes.btnCell); } if(cell.column.id == 'btn-edit' && row.isExpanded) { classNames.push(classes.expandedIconCell); } - return ( + return (modeSupported &&
    {cell.render('Cell', { reRenderRow: ()=>{setKey((currKey)=>!currKey);} @@ -490,13 +502,13 @@ export default function DataGridView({ /* Make sure to take the latest field info from schema */ field = _.find(schemaRef.current.fields, (f)=>f.id==field.id) || field; - let {editable, disabled} = getFieldMetaData(field, schemaRef.current, row.original || {}, viewHelperProps); + let {editable, disabled, modeSupported} = getFieldMetaData(field, schemaRef.current, row.original || {}, viewHelperProps); if(_.isUndefined(field.cell)) { console.error('cell is required ', field); } - return }
    ({style: {minWidth: 'unset'}}))} className={classes.table}> - +
    {rows.map((row, i) => { prepareRow(row); return + moveRow={moveRow} isHovered={i == hoverIndex} setHoverIndex={setHoverIndex} viewHelperProps={viewHelperProps}/> {props.canEdit && row.isExpanded && f.id==id)?.depChange; +} + describe('IndexSchema', ()=>{ let mount; + let indexSchemaObj; + let getInitData = ()=>Promise.resolve({}); - describe('column schema describe', () => { + /* Use createMount so that material ui components gets the required context */ + /* https://material-ui.com/guides/testing/#api */ + beforeAll(()=>{ + mount = createMount(); + spyOn(nodeAjax, 'getNodeAjaxOptions').and.returnValue(Promise.resolve([])); + spyOn(nodeAjax, 'getNodeListByName').and.returnValue(Promise.resolve([])); + indexSchemaObj = new IndexSchema( + { + tablespaceList: ()=>[], + amnameList : ()=>[{label:'abc', value:'abc'}], + columnList: ()=>[{label:'abc', value:'abc'}], + collationList: ()=>[{label:'abc', value:'abc'}], + opClassList: ()=>[{label:'abc', value:'abc'}] + }, + { + node_info: {'server': { 'version': 110000} } + }, + { + amname: 'btree' + } + ); + }); + + afterAll(() => { + mount.cleanUp(); + }); + + beforeEach(()=>{ + genericBeforeEach(); + }); - let columnSchemaObj = getColumnSchema({}, {server: {user: {name: 'postgres'}}}, {}); + it('create', ()=>{ + mount(getCreateView(indexSchemaObj)); + }); - it('column schema collection', ()=>{ + it('edit', ()=>{ + mount(getEditView(indexSchemaObj, getInitData)); + }); - spyOn(nodeAjax, 'getNodeAjaxOptions').and.returnValue([]); - spyOn(nodeAjax, 'getNodeListByName').and.returnValue([]); + it('properties', ()=>{ + mount(getPropertiesView(indexSchemaObj, getInitData)); + }); - mount(getCreateView(columnSchemaObj)); + it('create collection', ()=>{ + let schemaCollObj = new SchemaInColl(indexSchemaObj); + let ctrl = mount(getCreateView(schemaCollObj)); + /* Make sure you hit every corner */ + ctrl.find('DataGridView').at(0).find('PgIconButton[data-test="add-row"]').find('button').simulate('click'); + }); - mount(getEditView(columnSchemaObj, getInitData)); + it('changeColumnOptions', ()=>{ + spyOn(indexSchemaObj.indexHeaderSchema, 'changeColumnOptions').and.callThrough(); + let columns = [{label: 'label', value: 'value'}]; + indexSchemaObj.changeColumnOptions(columns); + expect(indexSchemaObj.indexHeaderSchema.changeColumnOptions).toHaveBeenCalledWith(columns); + }); + + describe('IndexColHeaderSchema', ()=>{ + it('getNewData', ()=>{ + indexSchemaObj.indexHeaderSchema.columnOptions = [ + {label: 'id', value: 'id'}, + {label: 'name', value: 'name'} + ]; + spyOn(indexSchemaObj.indexColumnSchema, 'getNewData'); + indexSchemaObj.indexHeaderSchema.getNewData({ + is_exp: false, + colname: 'id', + expression: null, + }); + expect(indexSchemaObj.indexColumnSchema.getNewData).toHaveBeenCalledWith({ + is_exp: false, + colname: 'id', + }); + + indexSchemaObj.indexHeaderSchema.getNewData({ + is_exp: true, + colname: null, + expression: 'abc', + }); + expect(indexSchemaObj.indexColumnSchema.getNewData).toHaveBeenCalledWith({ + is_exp: true, + colname: 'abc', + }); }); + }); + describe('IndexColumnSchema', ()=>{ it('column schema colname editable', ()=>{ - columnSchemaObj._top = { + indexSchemaObj.indexColumnSchema._top = { _sessData: { amname: 'btree' } }; - let cell = _.find(columnSchemaObj.fields, (f)=>f.id=='op_class').cell; + let cell = _.find(indexSchemaObj.indexColumnSchema.fields, (f)=>f.id=='op_class').cell; cell(); }); it('column schema sort_order depChange', ()=>{ let topState = { amname: 'btree' }; - let depChange = _.find(columnSchemaObj.fields, (f)=>f.id=='sort_order').depChange; + let depChange = _.find(indexSchemaObj.indexColumnSchema.fields, (f)=>f.id=='sort_order').depChange; let state = { sort_order: true }; depChange(state, {}, topState, { oldState: { sort_order: false } }); @@ -52,99 +149,76 @@ describe('IndexSchema', ()=>{ }); it('column schema sort_order editable', ()=>{ - columnSchemaObj._top = { + indexSchemaObj.indexColumnSchema._top = { _sessData: { amname: 'btree' } }; let state = {}; - spyOn(columnSchemaObj, 'inSchemaWithModelCheck').and.returnValue(true); - let editable = _.find(columnSchemaObj.fields, (f)=>f.id=='sort_order').editable; + spyOn(indexSchemaObj.indexColumnSchema, 'inSchemaWithModelCheck').and.returnValue(true); + let editable = _.find(indexSchemaObj.indexColumnSchema.fields, (f)=>f.id=='sort_order').editable; let status = editable(state); expect(status).toBe(false); - spyOn(columnSchemaObj, 'inSchemaWithModelCheck').and.returnValue(false); + spyOn(indexSchemaObj.indexColumnSchema, 'inSchemaWithModelCheck').and.returnValue(false); status = editable(state); expect(status).toBe(true); - columnSchemaObj._top._sessData.amname = 'abc'; + indexSchemaObj.indexColumnSchema._top._sessData.amname = 'abc'; status = editable(state); expect(status).toBe(false); }); it('column schema nulls editable', ()=>{ - columnSchemaObj._top = { + indexSchemaObj.indexColumnSchema._top = { _sessData: { amname: 'btree' } }; let state = {}; - spyOn(columnSchemaObj, 'inSchemaWithModelCheck').and.returnValue(true); - let editable = _.find(columnSchemaObj.fields, (f)=>f.id=='nulls').editable; + spyOn(indexSchemaObj.indexColumnSchema, 'inSchemaWithModelCheck').and.returnValue(true); + let editable = _.find(indexSchemaObj.indexColumnSchema.fields, (f)=>f.id=='nulls').editable; let status = editable(state); expect(status).toBe(false); - spyOn(columnSchemaObj, 'inSchemaWithModelCheck').and.returnValue(false); + spyOn(indexSchemaObj.indexColumnSchema, 'inSchemaWithModelCheck').and.returnValue(false); status = editable(state); expect(status).toBe(true); - columnSchemaObj._top._sessData.amname = 'abc'; + indexSchemaObj.indexColumnSchema._top._sessData.amname = 'abc'; status = editable(state); expect(status).toBe(false); }); it('column schema setOpClassTypes', ()=>{ - columnSchemaObj._top = { + indexSchemaObj.indexColumnSchema._top = { _sessData: { amname: 'btree' } }; let options = []; - columnSchemaObj.op_class_types = []; - let status = columnSchemaObj.setOpClassTypes(options); + indexSchemaObj.indexColumnSchema.op_class_types = []; + let status = indexSchemaObj.indexColumnSchema.setOpClassTypes(options); expect(status).toEqual([]); - columnSchemaObj.op_class_types = []; + indexSchemaObj.indexColumnSchema.op_class_types = []; options.push({label: '', value: ''}); - columnSchemaObj.setOpClassTypes(options); - expect(columnSchemaObj.op_class_types.length).toBe(1); + indexSchemaObj.indexColumnSchema.setOpClassTypes(options); + expect(indexSchemaObj.indexColumnSchema.op_class_types.length).toBe(1); }); - }); - let indexSchemaObj = new IndexSchema( - ()=>getColumnSchema({}, {server: {user: {name: 'postgres'}}}, {}), - { - tablespaceList: ()=>[], - amnameList : ()=>[{label:'abc', value:'abc'}], - columnList: ()=>[{label:'abc', value:'abc'}], - }, - { - node_info: {'server': { 'version': 110000} } - }, - { - amname: 'btree' - } - ); - let getInitData = ()=>Promise.resolve({}); - - /* Use createMount so that material ui components gets the required context */ - /* https://material-ui.com/guides/testing/#api */ - beforeAll(()=>{ - mount = createMount(); - }); - - afterAll(() => { - mount.cleanUp(); }); - beforeEach(()=>{ - genericBeforeEach(); - }); - - it('create', ()=>{ - mount(getCreateView(indexSchemaObj)); + it('depChange', ()=>{ + let state = {}; + expect(getFieldDepChange(indexSchemaObj, 'description')(state)).toEqual({ + comment: '', + }); }); - it('edit', ()=>{ - mount(getEditView(indexSchemaObj, getInitData)); - }); + it('columns formatter', ()=>{ + let formatter = _.find(indexSchemaObj.fields, (f)=>f.id=='columns').cell().controlProps.formatter; + expect(formatter.fromRaw([{ + colname: 'lid', + },{ + colname: 'rid', + }])).toBe('lid, rid'); - it('properties', ()=>{ - mount(getPropertiesView(indexSchemaObj, getInitData)); + expect(formatter.fromRaw([])).toBe(''); }); it('validate', ()=>{ @@ -152,7 +226,7 @@ describe('IndexSchema', ()=>{ let setError = jasmine.createSpy('setError'); indexSchemaObj.validate(state, setError); - expect(setError).toHaveBeenCalledWith('columns', 'You must specify at least one column.'); + expect(setError).toHaveBeenCalledWith('columns', 'You must specify at least one column/expression.'); state.columns.push({}); let status = indexSchemaObj.validate(state, setError);

    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 Qu=5K!DJ98@Z^nWD0}vrof&c&j literal 27305 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 tMhU{TqkF$C>~D diff --git a/docs/en_US/index_dialog.rst b/docs/en_US/index_dialog.rst index 79c1e2e78ed..5635a3329ac 100644 --- a/docs/en_US/index_dialog.rst +++ b/docs/en_US/index_dialog.rst @@ -8,7 +8,7 @@ Use the *Index* dialog to create an index on a specified table or materialized view. The *Index* dialog organizes the development of a index through the following -dialog tabs: *General* and *Definition*. The *SQL* tab displays the SQL code +dialog tabs: *General*, *Definition*, and *Columns*. The *SQL* tab displays the SQL code generated by dialog selections. .. image:: images/index_general.png @@ -76,28 +76,36 @@ Use the fields in the *Definition* tab to define the index: expression limits the entries in the index to those rows that satisfy the constraint. -Use the context-sensitive fields in the *Columns* panel to specify which -column(s) the index queries. Click the *Add* icon (+) to add a column: +Click the *Columns* tab to continue. -* Use the drop-down listbox in *Column* field to select the name of the column - rom the table. +.. image:: images/index_columns.png + :alt: Index dialog columns tab + :align: center + +Use the fields in the *Columns* tab to specify which column(s) or expression(s) +the index queries. Use the *Is expression ?* switch to enable +expression sql input. Use the drop-down listbox next to *Column* +to select a column. Once the *Column* is selected or the *Expression* is +entered then click the *Add* icon (+) to provide details of the action on the +column/expression: + +* The *Col/Exp* field is populated with the selection made in the *Column* + drop-down listbox or the *Expression* entered. * If enabled, use the drop-down listbox to select an available *Operator class* to specify the type of action performed on the column. -* If enabled, move the *Sort order* switch to specify the sort order: +* If enabled, use the drop-down listbox to select *Sort order*: * Select *ASC* to specify an ascending sort order (the default); * Select *DESC* to specify a descending sort order. - -* If enabled, move the *Nulls* switch to specify the sort order of nulls: +* If enabled, use the drop-down listbox to select *Nulls*: * Select *First* to specify nulls sort before non-nulls; * Select *Last* to specify nulls sort after non-nulls (the default). - * Use the drop-down listbox in the *Collation* field to select a collation to use for the index. Use *Include columns* field to specify columns for *INCLUDE* clause of the -index. This option is available in Postgres 11 and later. +constraint. This option is available in Postgres 11 and later. Click the *SQL* tab to continue. diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js index 11377e3ffb0..b3a7bb10235 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js @@ -7,7 +7,7 @@ // ////////////////////////////////////////////////////////////// -import IndexSchema, { getColumnSchema } from './index.ui'; +import IndexSchema from './index.ui'; import { getNodeAjaxOptions, getNodeListByName } from 'pgbrowser/node_ajax'; import _ from 'lodash'; @@ -46,7 +46,7 @@ define('pgadmin.node.index', [ hasSQL: true, hasDepends: true, hasStatistics: true, - width: pgBrowser.stdW.md + 'px', + width: pgBrowser.stdW.lg + 'px', statsPrettifyFields: [gettext('Size'), gettext('Index size')], url_jump_after_node: 'schema', Init: function() { @@ -124,13 +124,14 @@ define('pgadmin.node.index', [ getSchema: (treeNodeInfo, itemNodeData) => { let nodeObj = pgAdmin.Browser.Nodes['index']; return new IndexSchema( - ()=>getColumnSchema(nodeObj, treeNodeInfo, itemNodeData), { tablespaceList: ()=>getNodeListByName('tablespace', treeNodeInfo, itemNodeData, {}, (m)=>{ return (m.label != 'pg_global'); }), amnameList : ()=>getNodeAjaxOptions('get_access_methods', nodeObj, treeNodeInfo, itemNodeData, {jumpAfterNode: 'schema'}), columnList: ()=>getNodeListByName('column', treeNodeInfo, itemNodeData, {}), + collationList: ()=>getNodeAjaxOptions('get_collations', nodeObj, treeNodeInfo, itemNodeData, {jumpAfterNode: 'schema'}), + opClassList: ()=>getNodeAjaxOptions('get_op_class', nodeObj, treeNodeInfo, itemNodeData, {jumpAfterNode: 'schema'}) }, { node_info: treeNodeInfo diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.ui.js index acb337851e0..464369d2784 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.ui.js @@ -9,65 +9,79 @@ import gettext from 'sources/gettext'; import BaseUISchema from 'sources/SchemaView/base_schema.ui'; -import { getNodeAjaxOptions, getNodeListByName } from '../../../../../../../../static/js/node_ajax'; +import DataGridViewWithHeaderForm from '../../../../../../../../../static/js/helpers/DataGridViewWithHeaderForm'; import _ from 'lodash'; import { isEmptyString } from 'sources/validators'; import Notify from '../../../../../../../../../static/js/helpers/Notifier'; -export function getColumnSchema(nodeObj, treeNodeInfo, itemNodeData) { - return new ColumnSchema( - { - columnList: ()=>getNodeListByName('column', treeNodeInfo, itemNodeData, {}), - collationList: ()=>getNodeAjaxOptions('get_collations', nodeObj, treeNodeInfo, itemNodeData, {jumpAfterNode: 'schema'}), - opClassList: ()=>getNodeAjaxOptions('get_op_class', nodeObj, treeNodeInfo, itemNodeData, {jumpAfterNode: 'schema'}) - }, { - node_info: treeNodeInfo - } - ); + +function inSchema(node_info) { + return node_info && 'catalog' in node_info; } -export class ColumnSchema extends BaseUISchema { - constructor(fieldOptions = {}, nodeData = [], initValues={}) { +class IndexColHeaderSchema extends BaseUISchema { + constructor(columns) { + super({ + is_exp: true, + colname: undefined, + expression: undefined, + }); + + this.columns = columns; + } + + changeColumnOptions(columns) { + this.columns = columns; + } + + addDisabled(state) { + return !(state.is_exp ? state.expression : state.colname); + } + + /* Data to IndexColumnSchema will be added using the header form */ + getNewData(data) { + return this.indexColumnSchema.getNewData({ + is_exp: data.is_exp, + colname: data.is_exp ? data.expression : data.colname, + }); + } + + get baseFields() { + return [{ + id: 'is_exp', label: gettext('Is expression'), type:'switch', editable: false, + },{ + id: 'colname', label: gettext('Column'), type: 'select', editable: false, + options: this.columns, deps: ['is_exp'], + optionsReloadBasis: this.columns?.map ? _.join(this.columns.map((c)=>c.label), ',') : null, + optionsLoaded: (res)=>this.columnOptions=res, + disabled: (state)=>state.is_exp, node: 'column', + },{ + id: 'expression', label: gettext('Expression'), editable: false, deps: ['is_exp'], + type: 'sql', disabled: (state)=>!state.is_exp, + }]; + } +} + +class IndexColumnSchema extends BaseUISchema { + constructor(nodeData = {}) { super({ - name: null, - oid: undefined, - description: '', - is_sys_obj: false, colname: undefined, - collspcname: undefined, + is_exp: false, op_class: undefined, sort_order: false, nulls: false, - is_sort_nulls_applicable: true, - ...initValues + is_sort_nulls_applicable: false, + collspcname:undefined }); - this.fieldOptions = { - columnList: [], - collationList: [], - opClassList: [], - ...fieldOptions - }; this.node_info = { - ...nodeData.node_info + ...nodeData }; + this.operClassOptions = []; + this.collationOptions = []; this.op_class_types = []; } - get idAttribute() { - return 'oid'; - } - - // We will check if we are under schema node & in 'create' mode - inSchemaWithModelCheck(state) { - if(this.node_info && 'schema' in this.node_info) { - // We will disable control if it's in 'edit' mode - return !this.isNew(state); - } - return true; - } - setOpClassTypes(options) { - if(!options || (_.isArray(options) && options.length == 0)) return this.op_class_types; @@ -88,37 +102,52 @@ export class ColumnSchema extends BaseUISchema { return false; } + setOperClassOptions(options) { + this.operClassOptions = options; + } + + setCollationOptions(options) { + this.collationOptions = options; + } + + getNewData(data) { + return { + ...super.getNewData(data), + }; + } + + // We will check if we are under schema node & in 'create' mode + inSchemaWithModelCheck(state) { + if(this.node_info && 'schema' in this.node_info) { + // We will disable control if it's in 'edit' mode + return !this.isNew(state); + } + return true; + } + get baseFields() { - let columnSchemaObj = this; + let obj = this; return [ { - id: 'colname', label: gettext('Column'), - type: 'select', cell: 'select', noEmpty: true, - disabled: () => inSchema(columnSchemaObj.node_info), - editable: function (state) { - return !columnSchemaObj.inSchemaWithModelCheck(state); - }, - options: columnSchemaObj.fieldOptions.columnList, - node: 'column', + id: 'is_exp', label: '', type:'', cell: '', editable: false, width: 20, + disableResizing: true, + controlProps: { + formatter: { + fromRaw: function (rawValue) { + return rawValue ? 'E' : 'C'; + }, + } + }, visible: false, },{ - id: 'collspcname', label: gettext('Collation'), - type: 'select', - cell: 'select', - disabled: () => inSchema(columnSchemaObj.node_info), - editable: function (state) { - return !columnSchemaObj.inSchemaWithModelCheck(state); - }, - options: columnSchemaObj.fieldOptions.collationList, - node: 'index', - url_jump_after_node: 'schema', + id: 'colname', label: gettext('Col/Exp'), type:'', editable: false, + cell:'', width: 100, },{ - id: 'op_class', label: gettext('Operator class'), - tags: true, type: 'select', + id: 'op_class', label: gettext('Operator class'), tags: true, type: 'select', cell: () => { return { cell: 'select', - options: columnSchemaObj.fieldOptions.opClassList, - optionsLoaded: (options)=>{columnSchemaObj.setOpClassTypes(options);}, + options: obj.operClassOptions, + optionsLoaded: (options)=>{obj.setOpClassTypes(options);}, controlProps: { allowClear: true, filter: (options) => { @@ -126,12 +155,12 @@ export class ColumnSchema extends BaseUISchema { * to access method selected by user if not selected * send btree related op_class options */ - let amname = columnSchemaObj._top?._sessData ? columnSchemaObj._top?._sessData.amname : columnSchemaObj._top?._origData.amname; + let amname = obj._top?._sessData ? obj._top?._sessData.amname : obj._top?._origData.amname; if(_.isUndefined(amname)) return options; - _.each(this.op_class_types, function(v, k) { + _.each(obj.op_class_types, function(v, k) { if(amname === k) { options = v; } @@ -142,14 +171,13 @@ export class ColumnSchema extends BaseUISchema { }; }, editable: function (state) { - return !columnSchemaObj.inSchemaWithModelCheck(state); + return !obj.inSchemaWithModelCheck(state); }, node: 'index', url_jump_after_node: 'schema', deps: ['amname'], },{ - id: 'sort_order', label: gettext('Sort order'), - type: 'select', cell: 'select', + id: 'sort_order', label: gettext('Sort order'), type: 'select', cell: 'select', options: [ {label: 'ASC', value: false}, {label: 'DESC', value: true}, @@ -174,22 +202,38 @@ export class ColumnSchema extends BaseUISchema { } }, editable: function(state) { - return columnSchemaObj.isEditable(state); + return obj.isEditable(state); }, deps: ['amname'], },{ - id: 'nulls', label: gettext('NULLs'), - editable: function(state) { - return columnSchemaObj.isEditable(state); - }, - deps: ['amname', 'sort_order'], - type:'select', cell: 'select', + id: 'nulls', label: gettext('NULLs'), type:'select', cell: 'select', options: [ {label: 'FIRST', value: true}, {label: 'LAST', value: false}, ], controlProps: {allowClear: false}, width: 110, disableResizing: true, - }, + editable: function(state) { + return obj.isEditable(state); + }, + deps: ['amname', 'sort_order'], + },{ + id: 'collspcname', label: gettext('Collation'), + type: 'select', + cell: 'select', + disabled: () => inSchema(obj.node_info), + editable: function (state) { + return !obj.inSchemaWithModelCheck(state); + }, + options: obj.collationOptions, + node: 'index', + url_jump_after_node: 'schema', + },{ + id: 'statistics', label: gettext('Statistics'), + type: 'int', cell: 'int', disabled: (state)=> { + return (!state.is_exp || obj.node_info.server.version < 110000); + }, + min: -1, max: 10000, mode: ['edit','properties'], + } ]; } } @@ -298,12 +342,8 @@ export class WithSchema extends BaseUISchema { } } -function inSchema(node_info) { - return node_info && 'catalog' in node_info; -} - export default class IndexSchema extends BaseUISchema { - constructor(columnSchema, fieldOptions = {}, nodeData = [], initValues={}) { + constructor(fieldOptions = {}, nodeData = {}, initValues={}) { super({ name: undefined, oid: undefined, @@ -322,12 +362,16 @@ export default class IndexSchema extends BaseUISchema { tablespaceList: [], amnameList: [], columnList: [], + opClassList: [], + collationList: [], ...fieldOptions }; this.node_info = { ...nodeData.node_info }; - this.getColumnSchema = columnSchema; + this.indexHeaderSchema = new IndexColHeaderSchema(this.fieldOptions.columnList); + this.indexColumnSchema = new IndexColumnSchema(this.node_info); + this.indexHeaderSchema.indexColumnSchema = this.indexColumnSchema; this.withSchema = new WithSchema(this.node_info); } @@ -335,6 +379,16 @@ export default class IndexSchema extends BaseUISchema { return 'oid'; } + initialise() { + this.indexColumnSchema.setOperClassOptions(this.fieldOptions.opClassList); + this.indexColumnSchema.setCollationOptions(this.fieldOptions.collationList); + } + + changeColumnOptions(columns) { + this.indexHeaderSchema.changeColumnOptions(columns); + this.fieldOptions.columns = columns; + } + getColumns() { return { type: 'select', @@ -412,16 +466,15 @@ export default class IndexSchema extends BaseUISchema { }; }, deferredDepChange: (state, source, topState, actionObj) => { - const setColumns = (resolve)=>{ resolve(()=>{ - state.columns.splice(0, state.columns.length); + state.columns.splice(0, state.columns?.length); return { columns: state.columns, }; }); }; - if((state.amname != actionObj.oldState.amname) && state.columns.length > 0) { + if((state.amname != actionObj?.oldState.amname) && state.columns?.length > 0) { return new Promise((resolve)=>{ Notify.confirm( gettext('Warning'), @@ -431,7 +484,7 @@ export default class IndexSchema extends BaseUISchema { }, function() { resolve(()=>{ - state.amname = actionObj.oldState.amname; + state.amname = actionObj?.oldState.amname; return { amname: state.amname, }; @@ -443,22 +496,6 @@ export default class IndexSchema extends BaseUISchema { return Promise.resolve(()=>{/*This is intentional (SonarQube)*/}); } }, - }, - { - id: 'include', label: gettext('Include columns'), - group: gettext('Definition'), - editable: false, canDelete: true, canAdd: true, mode: ['properties'], - disabled: () => inSchema(indexSchemaObj.node_info), - readonly: function (state) { - return !indexSchemaObj.isNew(state); - }, - type: () => { - return indexSchemaObj.getColumns(); - }, - visible: function() { - return indexSchemaObj.isVisible(); - }, - node:'column', },{ type: 'nested-fieldset', label: gettext('With'), group: gettext('Definition'), schema: this.withSchema, @@ -529,29 +566,36 @@ export default class IndexSchema extends BaseUISchema { }, mode: ['create', 'edit'], control: 'sql-field', visible: true, group: gettext('Definition'), - }, { - id: 'columns', label: gettext('Columns'), type: 'collection', deps: ['amname'], - group: gettext('Definition'), schema: indexSchemaObj.getColumnSchema(), - mode: ['edit', 'create', 'properties'], - canAdd: function(state) { - // We will disable it if it's in 'edit' mode - return indexSchemaObj.isNew(state); - }, - canEdit: false, - canDelete: function(state) { - // We will disable it if it's in 'edit' mode + },{ + id: 'columns', label: gettext('Columns/Expressions'), + group: gettext('Columns'), type: 'collection', + mode: ['create', 'edit', 'properties'], + editable: false, schema: this.indexColumnSchema, + headerSchema: this.indexHeaderSchema, headerVisible: (state)=>indexSchemaObj.isNew(state), + CustomControl: DataGridViewWithHeaderForm, + uniqueCol: ['colname'], + canAdd: false, canDelete: function(state) { + // We can't update columns of existing return indexSchemaObj.isNew(state); - }, - uniqueCol : ['colname'], - columns: ['colname', 'op_class', 'sort_order', 'nulls', 'collspcname'] - }, { + }, cell: ()=>({ + cell: '', + controlProps: { + formatter: { + fromRaw: (rawValue)=>{ + return _.map(rawValue || [], 'colname').join(', '); + }, + } + }, + width: 245, + }) + },{ id: 'include', label: gettext('Include columns'), type: () => { return indexSchemaObj.getColumns(); }, - group: gettext('Definition'), + group: gettext('Columns'), editable: false, - canDelete: true, canAdd: true, mode: ['edit', 'create'], + canDelete: true, canAdd: true, mode: ['edit', 'create', 'properties'], disabled: () => inSchema(indexSchemaObj.node_info), readonly: function (state) { return !indexSchemaObj.isNew(state); @@ -590,7 +634,7 @@ export default class IndexSchema extends BaseUISchema { // Checks if columns is empty let cols = state.columns; if(_.isArray(cols) && cols.length == 0){ - msg = gettext('You must specify at least one column.'); + msg = gettext('You must specify at least one column/expression.'); setError('columns', msg); return true; } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_expr_statistics.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_expr_statistics.sql new file mode 100644 index 00000000000..f7c25eae1f2 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_expr_statistics.sql @@ -0,0 +1,14 @@ +-- Index: Idx3_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx3_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx3_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS LAST, lower(name) COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx3_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_name_fillfactor_comment.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_name_fillfactor_comment.sql new file mode 100644 index 00000000000..89a4e57b2ce --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_name_fillfactor_comment.sql @@ -0,0 +1,16 @@ +-- Index: Idx1_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx1_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx1_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default; + +ALTER TABLE IF EXISTS public.test_table_for_indexes + CLUSTER ON "Idx1_$%{}[]()&*^!@""'`\/#"; + +COMMENT ON INDEX public."Idx1_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_reset_fillfactor_cluster.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_reset_fillfactor_cluster.sql new file mode 100644 index 00000000000..d8c7cd5c5a3 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/alter_reset_fillfactor_cluster.sql @@ -0,0 +1,12 @@ +-- Index: Idx1_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx1_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx1_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST) + INCLUDE(name, id) + TABLESPACE pg_default; + +COMMENT ON INDEX public."Idx1_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_first.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_first.sql new file mode 100644 index 00000000000..4b2dab72fe2 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_first.sql @@ -0,0 +1,14 @@ +-- Index: Idx_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_first_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_first_msql.sql new file mode 100644 index 00000000000..26260514194 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_first_msql.sql @@ -0,0 +1,10 @@ +CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_last.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_last.sql new file mode 100644 index 00000000000..7d49e7c5fa8 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_last.sql @@ -0,0 +1,14 @@ +-- Index: Idx_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_last_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_last_msql.sql new file mode 100644 index 00000000000..7b00025c24a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_asc_null_last_msql.sql @@ -0,0 +1,10 @@ +CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_first.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_first.sql new file mode 100644 index 00000000000..d7f87ff1081 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_first.sql @@ -0,0 +1,9 @@ +-- Index: Idx_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST) + INCLUDE(name, id) + TABLESPACE pg_default; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_first_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_first_msql.sql new file mode 100644 index 00000000000..7492543e267 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_first_msql.sql @@ -0,0 +1,5 @@ +CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST) + INCLUDE(name, id) + TABLESPACE pg_default; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_last.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_last.sql new file mode 100644 index 00000000000..1aed1dd4a47 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_last.sql @@ -0,0 +1,14 @@ +-- Index: Idx_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_last_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_last_msql.sql new file mode 100644 index 00000000000..c72fd51c634 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_desc_null_last_msql.sql @@ -0,0 +1,10 @@ +CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_expr_asc_null_last.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_expr_asc_null_last.sql new file mode 100644 index 00000000000..f7c25eae1f2 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_expr_asc_null_last.sql @@ -0,0 +1,14 @@ +-- Index: Idx3_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx3_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx3_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS LAST, lower(name) COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx3_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_expr_asc_null_last_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_expr_asc_null_last_msql.sql new file mode 100644 index 00000000000..ada43a67b06 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/create_btree_expr_asc_null_last_msql.sql @@ -0,0 +1,10 @@ +CREATE UNIQUE INDEX "Idx3_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS LAST, (lower(name)) COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + INCLUDE(name, id) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx3_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/test_indexes.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/test_indexes.json new file mode 100644 index 00000000000..12182d16a14 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/11_plus/test_indexes.json @@ -0,0 +1,364 @@ +{ + "scenarios": [ + { + "type": "create", + "name": "Create Table for indexes", + "endpoint": "NODE-table.obj", + "sql_endpoint": "NODE-table.sql_id", + "data": { + "name": "test_table_for_indexes", + "columns": [{ + "name": "id", + "cltype": "bigint", + "is_primary_key": true + }, { + "name": "name", + "cltype": "text" + }], + "is_partitioned": false, + "spcname": "pg_default", + "schema": "public" + }, + "store_object_id": true + }, + { + "type": "create", + "name": "Create btree index with ASC and NULLS LAST -- 11 Plus", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "name":"Idx_$%{}[]()&*^!@\"'`\\/#", + "spcname":"pg_default", + "amname":"btree", + "include": ["name", "id"], + "columns":[{ + "colname":"id", + "collspcname":"", + "op_class":"", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }, { + "colname":"name", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }], + "description":"Test Comment", + "fillfactor":"10", + "indisunique":true, + "indisclustered":false, + "isconcurrent":false, + "indconstraint":"id < 100" + }, + "expected_sql_file": "create_btree_asc_null_last.sql", + "expected_msql_file": "create_btree_asc_null_last_msql.sql" + }, + { + "type": "delete", + "name": "Drop index -- 11 Plus", + "endpoint": "NODE-index.delete_id", + "data": { + "name": "Idx_$%{}[]()&*^!@\"'`\\/#" + } + }, + { + "type": "create", + "name": "Create btree index with ASC and NULLS FIRST -- 11 Plus", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "name":"Idx_$%{}[]()&*^!@\"'`\\/#", + "spcname":"pg_default", + "amname":"btree", + "include": ["name", "id"], + "columns":[{ + "colname":"id", + "collspcname":"", + "op_class":"", + "sort_order":false, + "nulls":true, + "is_sort_nulls_applicable":true + }, { + "colname":"name", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":true, + "is_sort_nulls_applicable":true + }], + "description":"Test Comment", + "fillfactor":"10", + "indisunique":true, + "indisclustered":false, + "isconcurrent":false, + "indconstraint":"id < 100" + }, + "expected_sql_file": "create_btree_asc_null_first.sql", + "expected_msql_file": "create_btree_asc_null_first_msql.sql" + }, + { + "type": "delete", + "name": "Drop index -- 11 Plus", + "endpoint": "NODE-index.delete_id", + "data": { + "name": "Idx_$%{}[]()&*^!@\"'`\\/#" + } + }, + { + "type": "create", + "name": "Create btree index with DESC and NULLS LAST -- 11 Plus", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "name":"Idx_$%{}[]()&*^!@\"'`\\/#", + "spcname":"pg_default", + "amname":"btree", + "include": ["name", "id"], + "columns":[{ + "colname":"id", + "collspcname":"", + "op_class":"", + "sort_order":true, + "nulls":false, + "is_sort_nulls_applicable":true + }, { + "colname":"name", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":true, + "nulls":false, + "is_sort_nulls_applicable":true + }], + "description":"Test Comment", + "fillfactor":"10", + "indisunique":true, + "indisclustered":false, + "isconcurrent":false, + "indconstraint":"id < 100" + }, + "expected_sql_file": "create_btree_desc_null_last.sql", + "expected_msql_file": "create_btree_desc_null_last_msql.sql" + }, + { + "type": "delete", + "name": "Drop index -- 11 Plus", + "endpoint": "NODE-index.delete_id", + "data": { + "name": "Idx_$%{}[]()&*^!@\"'`\\/#" + } + }, + { + "type": "create", + "name": "Create btree index with DESC and NULLS FIRST -- 11 Plus", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "name":"Idx_$%{}[]()&*^!@\"'`\\/#", + "spcname":"pg_default", + "amname":"btree", + "include": ["name", "id"], + "columns":[{ + "colname":"id", + "collspcname":"", + "op_class":"", + "sort_order":true, + "nulls":true, + "is_sort_nulls_applicable":true + }, { + "colname":"name", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":true, + "nulls":true, + "is_sort_nulls_applicable":true + }], + "indisunique":true, + "indisclustered":false, + "isconcurrent":false + }, + "expected_sql_file": "create_btree_desc_null_first.sql", + "expected_msql_file": "create_btree_desc_null_first_msql.sql" + }, + { + "type": "alter", + "name": "Alter index name, fill factor, comment and clustered -- 11 Plus", + "endpoint": "NODE-index.obj_id", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql_id", + "data": { + "name": "Idx1_$%{}[]()&*^!@\"'`\\/#", + "description":"Test Comment", + "fillfactor":"10", + "indisclustered":true + }, + "expected_sql_file": "alter_name_fillfactor_comment.sql", + "expected_msql_file": "alter_name_fillfactor_comment_msql.sql" + }, + { + "type": "alter", + "name": "Alter reset fill factor and cluster -- 11 Plus", + "endpoint": "NODE-index.obj_id", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql_id", + "data": { + "fillfactor": "", + "indisclustered": false + }, + "expected_sql_file": "alter_reset_fillfactor_cluster.sql", + "expected_msql_file": "alter_reset_fillfactor_cluster_msql.sql" + }, + { + "type": "delete", + "name": "Drop index -- 11 Plus", + "endpoint": "NODE-index.delete_id", + "data": { + "name": "Idx1_$%{}[]()&*^!@\"'`\\/#" + } + }, + { + "type": "create", + "name": "Create btree index with expression and ASC and NULLS LAST -- 11 Plus", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "name":"Idx3_$%{}[]()&*^!@\"'`\\/#", + "spcname":"pg_default", + "amname":"btree", + "include": ["name", "id"], + "columns":[{ + "colname":"id", + "collspcname":"", + "op_class":"", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }, { + "is_exp": true, + "colname":"lower(name)", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }], + "description":"Test Comment", + "fillfactor":"10", + "indisunique":true, + "indisclustered":false, + "isconcurrent":false, + "indconstraint":"id < 100" + }, + "expected_sql_file": "create_btree_expr_asc_null_last.sql", + "expected_msql_file": "create_btree_expr_asc_null_last_msql.sql" + }, + { + "type": "alter", + "name": "Alter index statistics of expression -- 11 Plus", + "endpoint": "NODE-index.obj_id", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql_id", + "data": { + "name": "Idx3_$%{}[]()&*^!@\"'`\\/#", + "columns":{ + "changed": [{ + "is_exp": true, + "col_num": 2, + "colname":"lower(name)", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true, + "statistics": 1000 + }] + } + }, + "expected_sql_file": "alter_expr_statistics.sql", + "expected_msql_file": "alter_expr_statistics_msql.sql" + }, + { + "type": "delete", + "name": "Drop index -- 11 Plus", + "endpoint": "NODE-index.delete_id", + "data": { + "name": "Idx3_$%{}[]()&*^!@\"'`\\/#" + } + }, + { + "type": "create", + "name": "Create hash index -- 11 Plus", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "name": "Idx_$%{}[]()&*^!@\"'`\\/#", + "spcname": "pg_default", + "amname": "hash", + "columns": [{ + "colname": "id", + "collspcname": "", + "op_class": "", + "sort_order": false, + "nulls": false, + "is_sort_nulls_applicable": false + }], + "indisunique": false, + "indisclustered": false, + "isconcurrent": false + }, + "expected_sql_file": "create_hash_index.sql", + "expected_msql_file": "create_hash_index_msql.sql" + }, + { + "type": "delete", + "name": "Drop hash index -- 11 Plus", + "endpoint": "NODE-index.delete_id", + "data": { + "name": "Idx_$%{}[]()&*^!@\"'`\\/#" + } + }, + { + "type": "delete", + "name": "Drop Table", + "endpoint": "NODE-table.delete_id", + "data": { + "name": "test_table_for_indexes" + } + }, + { + "type": "create", + "name": "Create unnamed hash index -- 11 Plus", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "spcname": "pg_default", + "amname": "hash", + "columns": [{ + "colname": "id", + "collspcname": "", + "op_class": "", + "sort_order": false, + "nulls": false, + "is_sort_nulls_applicable": false + }], + "indisunique": false, + "isconcurrent": false + }, + "expected_msql_file": "create_unnamed_hash_index_msql.sql" + }, + { + "type": "delete", + "name": "Drop hash index -- 11 Plus", + "endpoint": "NODE-index.delete_id" + } + ] +} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_first.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_first.sql index 79be5b2fd59..7a707969d2e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_first.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_first.sql @@ -5,6 +5,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST) + INCLUDE(name, id) WITH (fillfactor=10, deduplicate_items=False) TABLESPACE pg_default WHERE id < 100; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_first_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_first_msql.sql index 1ce641cdd04..a1547386a2b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_first_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_first_msql.sql @@ -1,6 +1,7 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST) + INCLUDE(name, id) WITH (fillfactor=10, deduplicate_items=False) TABLESPACE pg_default WHERE id < 100; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_last.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_last.sql index 0f94e381c6b..b4b7b6ec757 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_last.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_last.sql @@ -5,6 +5,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + INCLUDE(name, id) WITH (fillfactor=10, deduplicate_items=False) TABLESPACE pg_default WHERE id < 100; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_last_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_last_msql.sql index 27b27c31fbb..210314f3388 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_last_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_asc_null_last_msql.sql @@ -1,6 +1,7 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + INCLUDE(name, id) WITH (fillfactor=10, deduplicate_items=False) TABLESPACE pg_default WHERE id < 100; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_desc_null_last.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_desc_null_last.sql index 5a3d31b5e3d..f0faed97b8f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_desc_null_last.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_desc_null_last.sql @@ -5,6 +5,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST) + INCLUDE(name, id) WITH (fillfactor=10, deduplicate_items=False) TABLESPACE pg_default WHERE id < 100; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_desc_null_last_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_desc_null_last_msql.sql index 30119b40de8..61e5e8f1650 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_desc_null_last_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_btree_desc_null_last_msql.sql @@ -1,6 +1,7 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST) + INCLUDE(name, id) WITH (fillfactor=10, deduplicate_items=False) TABLESPACE pg_default WHERE id < 100; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/test_indexes.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/test_indexes.json index 5b598f5a382..31e555a670f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/test_indexes.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/test_indexes.json @@ -23,7 +23,7 @@ }, { "type": "create", - "name": "Create btree index with ASC and NULLS LAST -- 15 Plus", + "name": "Create btree index with ASC and NULLS LAST -- 13 Plus", "endpoint": "NODE-index.obj", "sql_endpoint": "NODE-index.sql_id", "msql_endpoint": "NODE-index.msql", @@ -31,6 +31,7 @@ "name":"Idx_$%{}[]()&*^!@\"'`\\/#", "spcname":"pg_default", "amname":"btree", + "include": ["name", "id"], "columns":[{ "colname":"id", "collspcname":"", @@ -60,7 +61,7 @@ }, { "type": "delete", - "name": "Drop index", + "name": "Drop index -- 13 Plus", "endpoint": "NODE-index.delete_id", "data": { "name": "Idx_$%{}[]()&*^!@\"'`\\/#" @@ -76,6 +77,7 @@ "name":"Idx_$%{}[]()&*^!@\"'`\\/#", "spcname":"pg_default", "amname":"btree", + "include": ["name", "id"], "columns":[{ "colname":"id", "collspcname":"", @@ -105,7 +107,7 @@ }, { "type": "delete", - "name": "Drop index -- 15 Plus", + "name": "Drop index -- 13 Plus", "endpoint": "NODE-index.delete_id", "data": { "name": "Idx_$%{}[]()&*^!@\"'`\\/#" @@ -113,7 +115,7 @@ }, { "type": "create", - "name": "Create btree index with DESC and NULLS LAST -- 15 Plus", + "name": "Create btree index with DESC and NULLS LAST -- 13 Plus", "endpoint": "NODE-index.obj", "sql_endpoint": "NODE-index.sql_id", "msql_endpoint": "NODE-index.msql", @@ -121,6 +123,7 @@ "name":"Idx_$%{}[]()&*^!@\"'`\\/#", "spcname":"pg_default", "amname":"btree", + "include": ["name", "id"], "columns":[{ "colname":"id", "collspcname":"", @@ -150,7 +153,7 @@ }, { "type": "delete", - "name": "Drop index -- 15 Plus", + "name": "Drop index -- 13 Plus", "endpoint": "NODE-index.delete_id", "data": { "name": "Idx_$%{}[]()&*^!@\"'`\\/#" @@ -158,7 +161,7 @@ }, { "type": "create", - "name": "Create btree index with DESC and NULLS FIRST -- 15 Plus", + "name": "Create btree index with DESC and NULLS FIRST -- 13 Plus", "endpoint": "NODE-index.obj", "sql_endpoint": "NODE-index.sql_id", "msql_endpoint": "NODE-index.msql", @@ -166,6 +169,7 @@ "name":"Idx_$%{}[]()&*^!@\"'`\\/#", "spcname":"pg_default", "amname":"btree", + "include": ["name", "id"], "columns":[{ "colname":"id", "collspcname":"", @@ -191,7 +195,7 @@ }, { "type": "alter", - "name": "Alter index name, fill factor, comment and clustered -- 15 Plus", + "name": "Alter index name, fill factor, comment and clustered -- 13 Plus", "endpoint": "NODE-index.obj_id", "sql_endpoint": "NODE-index.sql_id", "msql_endpoint": "NODE-index.msql_id", @@ -206,7 +210,7 @@ }, { "type": "alter", - "name": "Alter reset fill factor and cluster -- 15 Plus", + "name": "Alter reset fill factor and cluster -- 13 Plus", "endpoint": "NODE-index.obj_id", "sql_endpoint": "NODE-index.sql_id", "msql_endpoint": "NODE-index.msql_id", @@ -219,15 +223,85 @@ }, { "type": "delete", - "name": "Drop index -- 15 Plus", + "name": "Drop index -- 13 Plus", "endpoint": "NODE-index.delete_id", "data": { "name": "Idx1_$%{}[]()&*^!@\"'`\\/#" } }, + { + "type": "create", + "name": "Create btree index with expression and ASC and NULLS LAST -- 13 Plus", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "name":"Idx3_$%{}[]()&*^!@\"'`\\/#", + "spcname":"pg_default", + "amname":"btree", + "include": ["name", "id"], + "columns":[{ + "colname":"id", + "collspcname":"", + "op_class":"", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }, { + "is_exp": true, + "colname":"lower(name)", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }], + "description":"Test Comment", + "fillfactor":"10", + "indisunique":true, + "indisclustered":false, + "isconcurrent":false, + "indconstraint":"id < 100" + }, + "expected_sql_file": "create_btree_expr_asc_null_last.sql", + "expected_msql_file": "create_btree_expr_asc_null_last_msql.sql" + }, + { + "type": "alter", + "name": "Alter index statistics of expression -- 13 Plus", + "endpoint": "NODE-index.obj_id", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql_id", + "data": { + "name": "Idx3_$%{}[]()&*^!@\"'`\\/#", + "columns":{ + "changed": [{ + "is_exp": true, + "col_num": 2, + "colname":"lower(name)", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true, + "statistics": 1000 + }] + } + }, + "expected_sql_file": "alter_expr_statistics.sql", + "expected_msql_file": "alter_expr_statistics_msql.sql" + }, + { + "type": "delete", + "name": "Drop index -- 13 Plus", + "endpoint": "NODE-index.delete_id", + "data": { + "name": "Idx3_$%{}[]()&*^!@\"'`\\/#" + } + }, { "type": "create", - "name": "Create hash index -- 15 Plus", + "name": "Create hash index -- 13 Plus", "endpoint": "NODE-index.obj", "sql_endpoint": "NODE-index.sql_id", "msql_endpoint": "NODE-index.msql", @@ -252,7 +326,7 @@ }, { "type": "delete", - "name": "Drop hash index -- 15 Plus", + "name": "Drop hash index -- 13 Plus", "endpoint": "NODE-index.delete_id", "data": { "name": "Idx_$%{}[]()&*^!@\"'`\\/#" @@ -268,7 +342,7 @@ }, { "type": "create", - "name": "Create unnamed hash index -- 15 Plus", + "name": "Create unnamed hash index -- 13 Plus", "endpoint": "NODE-index.obj", "sql_endpoint": "NODE-index.sql_id", "msql_endpoint": "NODE-index.msql", @@ -290,9 +364,8 @@ }, { "type": "delete", - "name": "Drop hash index -- 15 Plus", + "name": "Drop hash index -- 13 Plus", "endpoint": "NODE-index.delete_id" } ] } - \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_name_fillfactor_comment.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_name_fillfactor_comment.sql index de7fef907fc..4260ca9569c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_name_fillfactor_comment.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_name_fillfactor_comment.sql @@ -5,6 +5,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx1_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST) + INCLUDE(name, id) NULLS NOT DISTINCT WITH (fillfactor=10) TABLESPACE pg_default; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_reset_fillfactor_cluster.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_reset_fillfactor_cluster.sql index 8b69df72b00..f429e8358d2 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_reset_fillfactor_cluster.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_reset_fillfactor_cluster.sql @@ -5,6 +5,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx1_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST) + INCLUDE(name, id) NULLS NOT DISTINCT TABLESPACE pg_default; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_first.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_first.sql index 9bfa43f7096..802e195002b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_first.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_first.sql @@ -5,6 +5,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST) + INCLUDE(name, id) NULLS NOT DISTINCT WITH (fillfactor=10) TABLESPACE pg_default diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_first_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_first_msql.sql index 0854aa63624..05b9ec8d72f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_first_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_first_msql.sql @@ -1,6 +1,7 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id ASC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS FIRST) + INCLUDE(name, id) NULLS NOT DISTINCT WITH (fillfactor=10) TABLESPACE pg_default diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_last.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_last.sql index 5ac5624e70b..2cf9c9e3a37 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_last.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_last.sql @@ -5,6 +5,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + INCLUDE(name, id) NULLS NOT DISTINCT WITH (fillfactor=10) TABLESPACE pg_default diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_last_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_last_msql.sql index 44727d7b9c2..53f42abb091 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_last_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_asc_null_last_msql.sql @@ -1,6 +1,7 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + INCLUDE(name, id) NULLS NOT DISTINCT WITH (fillfactor=10) TABLESPACE pg_default diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_first.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_first.sql index bde3398ba5c..6f6c8cd77fc 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_first.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_first.sql @@ -5,5 +5,6 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST) + INCLUDE(name, id) NULLS NOT DISTINCT TABLESPACE pg_default; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_first_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_first_msql.sql index 5859ffef20f..9660ac05a5f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_first_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_first_msql.sql @@ -1,5 +1,6 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id DESC NULLS FIRST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS FIRST) + INCLUDE(name, id) NULLS NOT DISTINCT TABLESPACE pg_default; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_last.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_last.sql index 50ea618736f..56ed7687856 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_last.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_last.sql @@ -5,6 +5,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST) + INCLUDE(name, id) NULLS NOT DISTINCT WITH (fillfactor=10) TABLESPACE pg_default diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_last_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_last_msql.sql index 1afc831eeaa..9eec0a7ff26 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_last_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_btree_desc_null_last_msql.sql @@ -1,6 +1,7 @@ CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#" ON public.test_table_for_indexes USING btree (id DESC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops DESC NULLS LAST) + INCLUDE(name, id) NULLS NOT DISTINCT WITH (fillfactor=10) TABLESPACE pg_default diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/test_indexes.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/test_indexes.json index dc2b3b0a711..a15d5dcfe0e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/test_indexes.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/test_indexes.json @@ -31,6 +31,7 @@ "name":"Idx_$%{}[]()&*^!@\"'`\\/#", "spcname":"pg_default", "amname":"btree", + "include": ["name", "id"], "columns":[{ "colname":"id", "collspcname":"", @@ -75,6 +76,7 @@ "name":"Idx_$%{}[]()&*^!@\"'`\\/#", "spcname":"pg_default", "amname":"btree", + "include": ["name", "id"], "columns":[{ "colname":"id", "collspcname":"", @@ -119,6 +121,7 @@ "name":"Idx_$%{}[]()&*^!@\"'`\\/#", "spcname":"pg_default", "amname":"btree", + "include": ["name", "id"], "columns":[{ "colname":"id", "collspcname":"", @@ -163,6 +166,7 @@ "name":"Idx_$%{}[]()&*^!@\"'`\\/#", "spcname":"pg_default", "amname":"btree", + "include": ["name", "id"], "columns":[{ "colname":"id", "collspcname":"", @@ -222,6 +226,76 @@ "name": "Idx1_$%{}[]()&*^!@\"'`\\/#" } }, + { + "type": "create", + "name": "Create btree index with expression and ASC and NULLS LAST -- 15 Plus", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "name":"Idx3_$%{}[]()&*^!@\"'`\\/#", + "spcname":"pg_default", + "amname":"btree", + "include": ["name", "id"], + "columns":[{ + "colname":"id", + "collspcname":"", + "op_class":"", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }, { + "is_exp": true, + "colname":"lower(name)", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }], + "description":"Test Comment", + "fillfactor":"10", + "indisunique":true, + "indisclustered":false, + "isconcurrent":false, + "indconstraint":"id < 100" + }, + "expected_sql_file": "create_btree_expr_asc_null_last.sql", + "expected_msql_file": "create_btree_expr_asc_null_last_msql.sql" + }, + { + "type": "alter", + "name": "Alter index statistics of expression -- 15 Plus", + "endpoint": "NODE-index.obj_id", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql_id", + "data": { + "name": "Idx3_$%{}[]()&*^!@\"'`\\/#", + "columns":{ + "changed": [{ + "is_exp": true, + "col_num": 2, + "colname":"lower(name)", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true, + "statistics": 1000 + }] + } + }, + "expected_sql_file": "alter_expr_statistics.sql", + "expected_msql_file": "alter_expr_statistics_msql.sql" + }, + { + "type": "delete", + "name": "Drop index -- 15 Plus", + "endpoint": "NODE-index.delete_id", + "data": { + "name": "Idx3_$%{}[]()&*^!@\"'`\\/#" + } + }, { "type": "create", "name": "Create hash index -- 15 Plus", diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/alter_expr_statistics.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/alter_expr_statistics.sql new file mode 100644 index 00000000000..51c1afec95b --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/alter_expr_statistics.sql @@ -0,0 +1,13 @@ +-- Index: Idx3_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx3_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx3_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS LAST, lower(name) COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx3_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/alter_expr_statistics_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/alter_expr_statistics_msql.sql new file mode 100644 index 00000000000..2f60ff734b3 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/alter_expr_statistics_msql.sql @@ -0,0 +1,2 @@ +ALTER INDEX IF EXISTS public."Idx3_$%{}[]()&*^!@""'`\/#" + ALTER COLUMN 2 SET STATISTICS 1000; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_btree_expr_asc_null_last.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_btree_expr_asc_null_last.sql new file mode 100644 index 00000000000..51c1afec95b --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_btree_expr_asc_null_last.sql @@ -0,0 +1,13 @@ +-- Index: Idx3_$%{}[]()&*^!@"'`\/# + +-- DROP INDEX IF EXISTS public."Idx3_$%{}[]()&*^!@""'`\/#"; + +CREATE UNIQUE INDEX IF NOT EXISTS "Idx3_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS LAST, lower(name) COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx3_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_btree_expr_asc_null_last_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_btree_expr_asc_null_last_msql.sql new file mode 100644 index 00000000000..53c401357a6 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_btree_expr_asc_null_last_msql.sql @@ -0,0 +1,9 @@ +CREATE UNIQUE INDEX "Idx3_$%{}[]()&*^!@""'`\/#" + ON public.test_table_for_indexes USING btree + (id ASC NULLS LAST, (lower(name)) COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST) + WITH (fillfactor=10) + TABLESPACE pg_default + WHERE id < 100; + +COMMENT ON INDEX public."Idx3_$%{}[]()&*^!@""'`\/#" + IS 'Test Comment'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/test_indexes.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/test_indexes.json index a85e2804a08..f8279fbf2aa 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/test_indexes.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/test_indexes.json @@ -150,6 +150,75 @@ "name": "Idx_$%{}[]()&*^!@\"'`\\/#" } }, + { + "type": "create", + "name": "Create btree index with expression and ASC and NULLS LAST", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "name":"Idx3_$%{}[]()&*^!@\"'`\\/#", + "spcname":"pg_default", + "amname":"btree", + "columns":[{ + "colname":"id", + "collspcname":"", + "op_class":"", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }, { + "is_exp": true, + "colname":"lower(name)", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true + }], + "description":"Test Comment", + "fillfactor":"10", + "indisunique":true, + "indisclustered":false, + "isconcurrent":false, + "indconstraint":"id < 100" + }, + "expected_sql_file": "create_btree_expr_asc_null_last.sql", + "expected_msql_file": "create_btree_expr_asc_null_last_msql.sql" + }, + { + "type": "alter", + "name": "Alter index statistics of expression", + "endpoint": "NODE-index.obj_id", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql_id", + "data": { + "name": "Idx3_$%{}[]()&*^!@\"'`\\/#", + "columns":{ + "changed": [{ + "is_exp": true, + "col_num": 2, + "colname":"lower(name)", + "collspcname":"pg_catalog.\"POSIX\"", + "op_class":"text_pattern_ops", + "sort_order":false, + "nulls":false, + "is_sort_nulls_applicable":true, + "statistics": 1000 + }] + } + }, + "expected_sql_file": "alter_expr_statistics.sql", + "expected_msql_file": "alter_expr_statistics_msql.sql" + }, + { + "type": "delete", + "name": "Drop index", + "endpoint": "NODE-index.delete_id", + "data": { + "name": "Idx3_$%{}[]()&*^!@\"'`\\/#" + } + }, { "type": "create", "name": "Create btree index with DESC and NULLS FIRST", diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/index_test_data.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/index_test_data.json index 27ab3066412..58ec65e3240 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/index_test_data.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/index_test_data.json @@ -79,7 +79,7 @@ } }, { - "name": "Create index: With valid data mumtiple.", + "name": "Create index: With valid data with multiple columns.", "is_positive_test": true, "inventory_data": {}, "test_data": { @@ -110,6 +110,39 @@ "test_result_data": {} } }, + { + "name": "Create index: With valid data with multiple columns and expressions.", + "is_positive_test": true, + "inventory_data": {}, + "test_data": { + "name": "test_index_add", + "spcname": "pg_default", + "amname": "btree", + "columns": [ + { + "is_exp": true, + "colname": "lower(name)", + "sort_order": false, + "nulls": false + }, + { + "colname": "id", + "sort_order": true, + "nulls": false + } + ], + "include": [ + "name" + ] + }, + "mocking_required": false, + "mock_data": {}, + "expected_data": { + "status_code": 200, + "error_msg": null, + "test_result_data": {} + } + }, { "name": "Create index: With invalid data - No column name.", "is_positive_test": false, @@ -507,6 +540,24 @@ }, "is_list": false }, + { + "name": "Put index statistics : With existing index id.", + "is_positive_test": true, + "update_statistics": true, + "inventory_data": { + }, + "test_data": { + "columns": "PLACE_HOLDER" + }, + "mocking_required": false, + "mock_data": {}, + "expected_data": { + "status_code": 200, + "error_msg": null, + "test_result_data": {} + }, + "is_list": false + }, { "name": "Put index : With existing index id while server is down.", "is_positive_test": false, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/test_indexes_put.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/test_indexes_put.py index 6609806f204..56e4018d5bb 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/test_indexes_put.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/test_indexes_put.py @@ -57,6 +57,8 @@ def setUp(self): self.schema_name, self.table_name, self.column_name) + if hasattr(self, "update_statistics"): + self.column_name = "lower(%s)" % self.column_name self.index_name = "test_index_delete_%s" % (str(uuid.uuid4())[1:8]) self.index_id = indexes_utils.create_index(self.server, self.db_name, self.schema_name, @@ -70,6 +72,15 @@ def runTest(self): self.index_name) if not index_response: raise Exception("Could not find the index to update.") + + if hasattr(self, "update_statistics"): + index_details = indexes_utils.api_get_index(self, self.index_id) + self.test_data['columns'] = {'changed': [ + {"is_exp": True, "col_num": + index_details.json['columns'][0]['col_num'], + "colname": self.column_name, + "nulls": False, "sort_order": False, + "statistics": "1000"}]} self.data = self.test_data self.data['oid'] = self.index_id diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/utils.py index c2e01c4b60b..9d1017c9911 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/utils.py @@ -117,6 +117,9 @@ def get_column_details(conn, idx, data, mode='properties', template_path=None): row['attdef'].strip('"'), 'collspcname': row['collnspname'], 'op_class': row['opcname'], + 'col_num': row['attnum'], + 'is_exp': row['is_exp'], + 'statistics': row['statistics'] } # ASC/DESC and NULLS works only with btree indexes @@ -245,6 +248,12 @@ def get_sql(conn, **kwargs): raise ObjectGone(_('Could not find the index in the table.')) old_data = dict(res['rows'][0]) + + # Add column details for current index + old_data = get_column_details(conn, idx, old_data) + + update_column_data, update_column = \ + _get_column_details_to_update(old_data, data) # Remove opening and closing bracket as we already have in jinja # template. if 'using' in old_data and old_data['using'] is not None and \ @@ -263,7 +272,8 @@ def get_sql(conn, **kwargs): sql = render_template( "/".join([template_path, 'update.sql']), - data=data, o_data=old_data, conn=conn + data=data, o_data=old_data, conn=conn, + update_column_data=update_column_data, update_column=update_column ) else: sql = _get_create_sql(data, template_path, conn, mode, name, @@ -353,3 +363,25 @@ def get_storage_params(amname): "heap": [] } return storage_parameters[amname] + + +def _get_column_details_to_update(old_data, data): + """ + This function returns the columns/expressions which need to update + :param old_data: + :param data: + :return: + """ + update_column_data = [] + update_column = False + + if 'columns' in data and 'changed' in data['columns']: + for index, col1 in enumerate(old_data['columns']): + for col2 in data['columns']['changed']: + if col1['col_num'] == col2['col_num'] and col1['statistics'] \ + != col2['statistics']: + update_column_data.append(col2) + update_column = True + break + + return update_column_data, update_column diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/column_details.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/column_details.sql index 491ff4d47c1..05c468df5f2 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/column_details.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/column_details.sql @@ -9,6 +9,8 @@ SELECT END::text[] AS options, i.attnum, pg_catalog.pg_get_indexdef(i.indexrelid, i.attnum, true) as attdef, + CASE WHEN pg_catalog.pg_get_indexdef(i.indexrelid, i.attnum, true) = a.attname THEN FALSE ELSE TRUE END AS is_exp, + a.attstattarget as statistics, CASE WHEN (o.opcdefault = FALSE) THEN o.opcname ELSE null END AS opcname, op.oprname AS oprname, CASE WHEN length(nspc.nspname::text) > 0 AND length(coll.collname::text) > 0 THEN diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/create.sql index 603255943d2..2800857d5d5 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/create.sql @@ -3,7 +3,7 @@ CREATE{% if data.indisunique %} UNIQUE{% endif %} INDEX{% if add_not_exists_clau ON {{conn|qtIdent(data.schema, data.table)}} {% if data.amname %}USING {{conn|qtIdent(data.amname)}}{% endif %} {% if mode == 'create' %} - ({% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{{conn|qtIdent(c.colname)}}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.op_class %} + ({% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{% if c.is_exp %}({{c.colname}}){% else %}{{conn|qtIdent(c.colname)}}{% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.op_class %} {{c.op_class}}{% endif %}{% if data.amname is defined %}{% if c.sort_order is defined and c.is_sort_nulls_applicable %}{% if c.sort_order %} DESC{% else %} ASC{% endif %}{% endif %}{% if c.nulls is defined and c.is_sort_nulls_applicable %} NULLS {% if c.nulls %} FIRST{% else %}LAST{% endif %}{% endif %}{% endif %}{% endfor %}) {% if data.include|length > 0 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/create.sql index 4f0a1e911e7..f1994631c70 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/create.sql @@ -3,7 +3,7 @@ CREATE{% if data.indisunique %} UNIQUE{% endif %} INDEX{% if add_not_exists_clau ON {{conn|qtIdent(data.schema, data.table)}} {% if data.amname %}USING {{conn|qtIdent(data.amname)}}{% endif %} {% if mode == 'create' %} - ({% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{{conn|qtIdent(c.colname)}}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.op_class %} + ({% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{% if c.is_exp %}({{c.colname}}){% else %}{{conn|qtIdent(c.colname)}}{% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.op_class %} {{c.op_class}}{% endif %}{% if data.amname is defined %}{% if c.sort_order is defined and c.is_sort_nulls_applicable %}{% if c.sort_order %} DESC{% else %} ASC{% endif %}{% endif %}{% if c.nulls is defined and c.is_sort_nulls_applicable %} NULLS {% if c.nulls %} FIRST{% else %}LAST{% endif %}{% endif %}{% endif %}{% endfor %}) {% if data.include|length > 0 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/column_details.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/column_details.sql index dc9d79ee2e2..9e79b0cff67 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/column_details.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/column_details.sql @@ -9,6 +9,8 @@ SELECT END::text[] AS options, i.attnum, pg_catalog.pg_get_indexdef(i.indexrelid, i.attnum, true) as attdef, + CASE WHEN pg_catalog.pg_get_indexdef(i.indexrelid, i.attnum, true) = a.attname THEN FALSE ELSE TRUE END AS is_exp, + a.attstattarget as statistics, CASE WHEN (o.opcdefault = FALSE) THEN o.opcname ELSE null END AS opcname, op.oprname AS oprname, CASE WHEN length(nspc.nspname::text) > 0 AND length(coll.collname::text) > 0 THEN diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/create.sql index 34b8d3c70d5..ea3ce45f872 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/create.sql @@ -3,7 +3,7 @@ CREATE{% if data.indisunique %} UNIQUE{% endif %} INDEX{% if add_not_exists_clau ON {{conn|qtIdent(data.schema, data.table)}} {% if data.amname %}USING {{conn|qtIdent(data.amname)}}{% endif %} {% if mode == 'create' %} - ({% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{{conn|qtIdent(c.colname)}}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.op_class %} + ({% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{% if c.is_exp %}({{c.colname}}){% else %}{{conn|qtIdent(c.colname)}}{% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.op_class %} {{c.op_class}}{% endif %}{% if data.amname is defined %}{% if c.sort_order is defined and c.is_sort_nulls_applicable %}{% if c.sort_order %} DESC{% else %} ASC{% endif %}{% endif %}{% if c.nulls is defined and c.is_sort_nulls_applicable %} NULLS {% if c.nulls %} FIRST{% else %}LAST{% endif %}{% endif %}{% endif %}{% endfor %}) {% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/update.sql index 71cdb754e48..bef61d07f1d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/update.sql @@ -85,3 +85,12 @@ ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}} {% if data.description is defined and o_data.description != data.description %} COMMENT ON INDEX {{conn|qtIdent(data.schema, data.name)}} IS {{data.description|qtLiteral(conn)}};{% endif %} + +{## Alter column statistics##} +{% if update_column %} +{% for col in update_column_data %} +ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}} + ALTER COLUMN {{col.col_num}} SET STATISTICS {{col.statistics}}; + +{% endfor %} +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/static/js/privilege.ui.js b/web/pgadmin/browser/server_groups/servers/static/js/privilege.ui.js index 1b5bf531250..d2e6caad862 100644 --- a/web/pgadmin/browser/server_groups/servers/static/js/privilege.ui.js +++ b/web/pgadmin/browser/server_groups/servers/static/js/privilege.ui.js @@ -62,7 +62,7 @@ export default class PrivilegeRoleSchema extends BaseUISchema { disabled : function(state) { return !( obj.nodeInfo && - obj.nodeInfo.server.user.name == state['grantor'] + obj.nodeInfo.server?.user?.name == state['grantor'] ); }, }, diff --git a/web/pgadmin/static/js/SchemaView/DataGridView.jsx b/web/pgadmin/static/js/SchemaView/DataGridView.jsx index 61a78e0a3e9..d43cbdd1434 100644 --- a/web/pgadmin/static/js/SchemaView/DataGridView.jsx +++ b/web/pgadmin/static/js/SchemaView/DataGridView.jsx @@ -133,8 +133,12 @@ const useStyles = makeStyles((theme)=>({ } })); -function DataTableHeader({headerGroups}) { +function DataTableHeader({headerGroups, viewHelperProps, schema}) { const classes = useStyles(); + + /* Using ref so that schema variable is not frozen in columns closure */ + const schemaRef = useRef(schema); + const sortIcon = (isDesc) => { return isDesc ? ' 🔽' : ' 🔼'; }; @@ -142,21 +146,24 @@ function DataTableHeader({headerGroups}) {