Command Triggers, v16

Started by Dimitri Fontainealmost 14 years ago50 messages
#1Dimitri Fontaine
dimitri@2ndQuadrant.fr
1 attachment(s)

Hi,

I guess it's time to start a new thread here. Please find attached
version 16 of the command trigger patch, with augmented documentation
and “magic variable” support (TG_WHEN, TG_OBJECTID and such).

The current version of the patch only supports PLpgSQL, I need to add
support for the other languages in core but I though Thom would like to
be able to play with a new patch before I finish plpython, plperl and
pltcl support.

This patch also includes edits following latest reviews from both Thom,
Andres and Robert, in particular ANY command triggers are now called
from the same place as specific command triggers and receive the same
parameters.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

Attachments:

command-trigger.v16.patch.gzapplication/octet-streamDownload
�\/bO�=kw�6���_����$�%�'��Q$��^Y�Jr����dn(R%)��m�����HP�I������`f0���W��]sC�G��d��f�l��W�����6-����o����ue��>�"�k����os:��B�N�0 W�v���[�~��"��fk>�=�N(��4"��[�I���}
=��3�Nb���kG����Nm6���sR��Y�������FS,x�#�������a��p�K=��������$$.{%I�M&4pfQ�Pw��J�.+%^L��U.�����P��N�v���=�1���U�9h_tOj02�����oG^0!^B���d<�@��G��������m�=���7�To�S[��Qg��I�%>�xiL!�Nl�������x5���yo�����
�u�e�����c���pl;	�[\I<�C��W>^��w|F��^Wv��������@�������h1-oJqy����IdO}/No�������p:��d����L]e��Jf[�)N�Z�S��DS�����z��������d>�AM�E4�GI3J�1�	~��M��V{j�?��
�>��`���=$��}���p���[�>�g����-�h�@x��2��'��"�u�2/	g�>�����/U2����6�m	e.�u(�o`j�%��1�=X�S�����qvR���;��dk&�	�Jtq�?-�Bl>�d$����K$�	L��^#�$�4{�����&P����^D�j�DM������Q�QO�|���~5��$N�����MPz������4�oLI+�����tF��
2X
�6c��=�o����n=%C�M��4����:���R���Fgd
������j���U�����vRMh������3)��������y��8����F�=H���
���$��Og�t�|S*�]Cp�1�	���P�s4���S^E\ejt}�>�a�0�)-�v����.1�������9�3p����	n���=�c�{���Fk[�fu��whVQ��z=��	����9�Cy���q[�����H��\J�&cN7�f��$���8!���M�Tp.���7Mi�i�j��
�1���lF�8%;�0��'�^���$oOo	�	����|�Q�q{�s��%B�b�'�|p���"�20��?��#:����	Q�`�M�-�	���D>���f%[Y�^�q���/`���\�ze�|��>���" �����w�xAi^�8.��G��a�����"�P;��y��=��$��{�-�?[��d��$��e����X�5�Z����1�b#�s���+b"�4 1��>��Y�]I�#�+��q�SN'	�E����sx�������x�"����s���fu��lnL&���h]�jh�������bgG���[��ln����f�C!�����<YW����Sb@�u�}�����e���\M`�r�y�p�6��L�q�S9<|"�8���.�_w�lK�y����M�v��K�v����*'��K�D�6
J���H(��`,�F��\�%�":���f���n�p�yS9~*�q�S9>*z�"H������
4���-�MS�nK���5
���J$8Uw�!,l����q`]Ua�w�������%[O��4
�$l�����e��~����n��0N@"���,(��
�������a�Lh����W��8�5�����7.���&�L;
{{���~'5���
�`>��>�e)��;^0���6�Hc��S�cp�f����Dm(��� 3_�SV�6���Y�:�3�)��0�?�*�Sl��YY�'��~
y6mB(�x.��������|8�� #?^�,�b�����#T��f�����������c*m�,Vn��:L�C�p��O�B�B_�.V��w������@��6��!�9L-��[� 1s��K�|l\����u�i7�����n
�hk����e��`�fe�=)�3����yY��K]�2�rr��'7��2��Ec'�f������}��%KCV������~�e+���w�������`�u8'Stu�������&!�8A-�(�"�/������	�)�o�����}��*��r���ob��Y�6J�T�(������bl� ���B%��"k�����=	d�[0W7L%a�O��
�<���4Fl����0
}�D|R��p�C��.$����-�D�xx��'w�c5���:�����ca- ����O��k�����@G�����8���oxh�42x2����k�v0�x����(^���;�����9���\mO���YeO�ObP�S�{[��0����^����	6����������e(>��6�}��O��p���'it�%di"~��W0�e��i������d�{h����6
+�
��I��,�5�g���7���Y�:�j��F�\t:
�v��v�z�|q�������O�[h���>��Vc� {��K�gl0P�Q#�o��N�{v�8�[^����g,$�N��7W�6���k���@�E����n���~��R$aL���^�g��i���W�����f47z��M@�������u~����XKz�����
��s��v�L���m}��U�+6/a�B�%*-���(�dJ���J&f�KU��:'��.���mY����������J5i��i�&*{Wy�4	�e�����2������ ��6��s�([h�(3Q%Y5�0�z��c��v��9Q�9Ad�������%"�����+t�ce����������ie���5���*E���&p�D7Q�+)��J�
�
bVh�	Y�6'b�^0^���6+WD�s�����2=�4�WW��!�Tf8fQ&f}���5J
����h?��:����@�����B}�Cz���]k����6�2#	SDZ)O�Ls0�yP}H����2���%f���P�(�MM� �<��8#���D�o��`�F��D�	�-��G�q2�h�a�]�=Zpp����-�r�,K�\����OI������;��*�[Kk�-xi99t��Kse�l���Q�$|u���V���&"�V���G?�H2g�x�	d�>-Y�+����l���&aE4�y�]!��|�
��!�Y��l`�q"��
���m9�E&���!a	O�>A�B���W8X:}?�c����J �����B�p�O[��8�,��������3��!��_����p�����9V���E��U��k6%(P��f2����2�8
�i�c
���b�S9S�Q�HV�aA���2<k����3��5C�e��9&��sY��dx'n
�%Fm���+�4��:���m�{���9L�I!���Rb <����j��PM1�b���<{"�
�����?�I�2-0�O�N�*X�J��}�'Ws�;�
+M.	0���T�|�	oJ����b�T��G��Hl��s�R�El-�3�x���L��?���K+�v�B�%o6����[!^�~�}DrG���6��huR����R��"A������	��0k�Al�����	�"��!�Al�5��V�	l,��2������.o��Ta�n���)�LS��R8�D��T�*>P����������������s�BD����N�O����i����Z���K�%�Z�i��	�\�/�l)b�Q&����`,�������(&4��T&�hz��,�����Rc�\���������X���v��^�$�AV�����B�vP�1����-��e���2
O�jt:Mu�L�Q�J��	;L(�e��\2��5h�����g
,��"���t����Nd�k�2�mQ.�`<�#/Y�����t��
kK����40���@��fD|����D��3��:QtN�0H��t�-zrBV��eg��.q�-x�!��@�����p~��B�N�f+[��\gQx�����~��m��+E�����R;P�+���J]�]��X��D�M#�vPn,V�����w�
�@9�RhFq1�JrI[y�AMN�TU����% i����e:A����
���16��~7(�9���n���$��7�`;t�����\=����`�&l���I-p�'L	f���aX���C�r�r�]����w����[e,@�Pn�z�U���E���c���J��i*r���S_�#*=�ZP���l��J���F���:��{,%c����}7a|����Q�H��_z����m`�74�C4���� ��v��T�.vv��R�
�k+�W��5�>p������e�-���.�c�%J���4�F�#}9h�:�������R��j6���"����������U��/,#y� ���F��2cf��?�b}jZ�l�M	�'�#<v����O~�/YY��vM����#�V��&�����x�e��8K�_gk�[�b$��C����d�Yd�������*v"b�;y��A3i@��s�>�%7���_�n��T��K�{l�K^l���f&���8n����gK��$���\� c�[��f�Z�;����87���9Q�)�Qb�l-����Q��6���4�K��(�T��9�'���bZW3	���%����O�����wL8�kk�.�F\���X9�W�� }�HKk�; �><���I�w����F�����T'>5
~������W�eu�g��������F��,1����+�;K/��q[jogUv'��$���p�;������u�"j��,3���iZ�z^��Gfu���*�����������Y��?���5�n�����f~�����x���&�YB����3�"!��q|��������}��Z��g7Qx��E!���K"�_(�����+����s�Ys��E��w{�)/�8�������:E4�Y�F�H��g��,�����'��CU2YDP����J�� L��S�6f�nF�6E"�@f��4z�lyj�����"�J|��NKL�GDI`[I�p�1#���tQO���r���rh<X%�`t	��
�� .�u��X�a������������r�(]���-L��^��u�T�����#d����q�N/P���sjy�E��oc��a^����8Xpn�f�.�I��9���+���aewW����3O�,�"�uJLo��:(�����`��9���(S�{�������������R���c%Zc����
��?/���+=�������z��h��RD'0���7����m�\���Q8f�A�3�
osX/bJ��y/I�l�=E
]�����v|f����"S���,�R{���F��C�L>G�����^- ��Zl��e�7����6~�����%��^IzK6;AP��c��&xt�4���[5�
���f�"�Cw7!>+Dyj�Z����!�e��<M<2������M��~\x�Py�mK�����|�0s47��������8\]#�A�k�0L���g�7v�W]�����qE�V���F"����l�m�'��-�����|w��|�9z�t��/�fl������K'�<���;	�
�����?�O����D����r���F�^��w��Sr���%���&T���Hr
��0����V�I�'�s��7�����<��}��./��3p����=���}��<a����;����!��z�K6�8����H��C|g���$���
�'p�{A�����F^�/�+>'c'a_P8�S�_�,��?�����o�B��;��Y5���r�s��Z�Z
5R����C�=&�7��!@KC�}�Y�P�����i0�����lSF�w� ����j�z���>�I����g`�r+M�����
R��!wc��t`������\B��3�L��*	(WG�%�E�Y���fF3�t�b���.����!�*�-��
��l�e�V&�F�p�m�����E�a~7u�r�&c��A�hg)��x��B���XR���DS���%���f�M���3�����Ei:����=��o*�G|sck�!����sE�q���?�7>
/���_a��'.��0��$��qL����h��j�o:����61yU�~����R�������+:�u�_��e�6�l
���a���j���7���;��3w��v�-����"�RJ&�oNe�A�K��y.C�9��#=�G��������O�!DL���8&�����7n�����=�PX�����>��s�Qc�o��DB�PC�#+���[��F7�A��8'�=ch�������5����	u:�i[g2/A��,��Xc��G�&��}K����v/�������|�G�oBn>q�$�����������B4�������j��V�
����_2,��,��|����5	�x��
3�����U�s��X�������&&��j���%E�P6@+�����P�L�`��@'�Zs
�8zxR�����'��$�#Pdo8�f?��T�"������7��>����Y^G��|����/V����\��C �#�R$����=56P��Y�Y��A���0�)O����1��,X���)����w���@�.����j������Z|����!��K��^�w������,]}����m�`��b������U0��%�rW�G�qHN���L��ys���ix�:�6�n5��\���.K<�ap��^��G?��b	>?8�#�p��z���s�RT����
����i����?���9;V"�m<L��F��C�bxq�������7p;��y�Xb�.�7/��T`���_����s�j9p+9$����*,}u�B����J�j�Q���`����I[f������8*6��6:�N���b���t���0�5���=�!�#�azt8{����������d�m��O�5
�����D��,+����]�����VG��[�����<��a8un�sP����"������|���E�Zb�� R��`�2L;��2�u��F��btg?��5�D����XRE��K��X�p�C�[�2^�B\�w�(���&����U�F�5��la������L��z��.������X�M������O���$���T�q����0|�4P��}���f+!�����e��J+��.��\f�s$�4�G�B8�>����Gp���	����s*�p'1=�@��)��4��h0IW�~��u�r�O�.��E���q�+E
���7�����n��/:��n�����"�a���Z>���uj�U]�+������|����c����Q�4��jT�8q�7�q�����{��5����w��a����_g��N��0)c�X���`:9T�	?�(�B������+�j�][(*� PCkdbB/Z��+i�iv�������A����-*Z-�k��l7�Z�\�E3m<���o��������������S=1�f4o������%��HI&aT�$�x9����3��Q<r(�9���>{�N���`e
������
�3`\U���,�b��4��v{P�W
0o�;tW�N������
�����X2�u&����������K�K�:��8��
�|%�kt�;��;�qG~�I���:g+�d����A�#����Qn�a���&���5i6�"+�orW��o��*R1���vc���^o��"��Ai���8
`G�������+��*�5&;@t"����K�Xk���J	���v]��}-N�U����m�U��U�?����h��`�B]��������f"���l������J���){��R��u�[��p�u6"�����fv�m
D���co��T�u�*�9����g\��]���7�;F�r��V4A�Q��FR.�(�L�U��x��
��7�o��7�9qH8�����@������s�j\G�d]��Q�@G���g�4q�h�K��`���PL4Zph���
^�������J������6�c���[ QM����1B[W�f��x��6���tO.tc�2
q���P8h+�Eb!���`#h��p��r�K��OM*�����\�X�)�!���$?;+��H*
}�Q���2��|�c��.*�=�{�[q�W���p�4�m�g��BW��w�����qIt(���OJj����Z\��j��	N*�u ��V�S��UzNo�9�%�n���OCf��6�JY-�(���{���c��Sne�c&��������c�c��T7�D�+���hO	C��~���)���rA�t���D9_��{�\�PRz�F�g,K(����zyS����r�oOnI��H|wTNY^0v,Dz`����������+�]q�l��Ol7�;����@�@���3l�hh~;\]��e9�Dk�*R�����a��o���'�fj�U4��y��	���->4��v���4O��ID/j, �S�Xw���6F��L�vF��6�|��Z��\��jni�B�
������,���"�R�Q���N�SK������#��%^��T	�]��e5G
2�
���DC�]^s����s�{v���{����%S����m���e���������m�a��pe�!��U=�#2f	G�M�S�Fc����7��Y�E���\�G^\`�������	I0i�.���k<L�X�:�����LS�-���Y��i��jk��a_!����x�4�R��'�\�{t2�8���U�
��zK����_"���Y��_��['�����>Hy+�4�%����Jk�=�PO��J�&�\�PRl`�#'���c���5��N�� gq)A������V+�5�����M'�K������X�f��n�#z�"�*?v���Y����_F����]�����������8�T�F�&v�0�e_7��i�u�7��n�pI�Y��nv��y�o~�\bw�X�W�e0���o�"������KoAJN�_L����3����.���Wv�^������a�dF�YB3gJz�����c��?C�9~�����NK�i�m���M�R/�@l�h���NIxq��"�)������W�����f�$�J���!@Be
]�uV���F��}u�����!�����m�M�9�N�9m�~�]��@��\�r�����thq����I��`�M7X�^��=�z�
��/~��!P��i���0f���+nE��!O��4�h
W�'OQ��i:������5�.��P��.S)������=�Y��T���[Ukg��jM�m��������h�=0�l����c]�/_�w�Hk3�f���$^����&M��5��d^IM#5�2��i�[d���Vs�����B�W���c+�C���~Z@�8&�C���T�lKb�F�A���(dp2s�t�����m�'R�M���
E��o�����S7�2#��_G��oU-4�n����H���
�N�@v������_���f(��3��?�'
�r	����:�����UZs��71�G�jT��������h#��d<�>��(
�g��X�����o������O�"���g{0��%H�(���oe��.�/
pt�*���Z_%PTs(��=�l���P��C���mL�
X�\O�BC&gG��Y�I3F?[�c�Z�Y����F�E7�$rm�����-�5�)��$����G��5?Z��6�����?CJ������d|�NNuI���^������s1����d�����5���?T����_j�1c�1���"e������-�bu�gZ����3�kVg��V���*"K�.���l��n�jp�%�����G{����7:�tv����#���ImU��P8�4���j�#/o�,^U������#�3c��0�j�rK��#�������}����l��]��4��N��l���T�hb��x~_��\�	�L�^��������e����b!@z�}����w/{(�%�+j,�����������U%��@�n���7h��n�s�?w�������?KE��|��v�����j�m���L&|3Qp��`������1>����ka�������T�#fw*���}��}u;7rS���LUh��c�R�Qm���a�����������D����l���'/�Y���M������������� ��������[���Fb8��l�	����\������*M�j�q�C�����������~6���^���8��I���X��9��!y���{��t���C���@�����sp���_)�)�%��E/W�F4�)4����8E��#��R�W?I�S�O�#����?��r����nE��3A8�;�����lWe���u�b-���L�9��^�sM�7��������>��;"�<_�OZ):H�;��R9Ly_w��\����j��W� Q�3D��D���$��ruMP{����^�=���������G�'�Dzg*�������4}2�'����i��������7e����$�1?�Fp�M{�m��,��I�.u��
2l�R5�4/vUn��D�D�zF�YV��9B8_KIyc�gWr�2!��l!O#��.RO�(<P1������I�����u�m�*���!'�����F>����(�������F�R����nE��>������h��3Y���pWX�
���
�]�Uo�u�������RO�,�I��)+���p��1"W��|��B�_�g��q9b�A��=g)�t��'��S�J����Mg"n��]�������%���)��3�+�
���sTe"=�Vk�V���3��1nlc�|�oF>3Rdu0y���}&���/��w�����HD���q�vq�/HeQM��F�4��Y�#�Ww��G���s�����&��V����N����g$���e����u�
M+c�|�<f$�.��k�xRJ�������XX�UXka]"!��!��L���A)���:���S�mx��q��M��k�J��	;f���nx\G������+,i�4�����1�2�[���s��$��T�P�����w>L�Rn���}�X�vc�n�}jo^��
XG&+5_���w�S:
�>�`V���Itm�Qy6�m{R����$+�A�� *ztWxj�%���[]sz�����������V��
Wb������:�������w�T��{��S��y����18���F��9g��-a�q�w?�O~I���n�t������-�����'����`f��v��E��K���\->�n0��x������������]cMC��<���9*8�T���T���gT*�8p�x����~N�
IW��?M�X�J]�e=���4=@�8��?)N�Y;oY�6�������	��d��q'��>Q���/���9��[�?t�8��1��9���9����4k+�e�;������$���,�2��e��J�N��D��]��}6��8
��G��(������<�z�)>�NJ��6?.y=�Cc����-p�h�R�qd�����i�v(T�s���<C�g$�c��H\�����a3��*3�"
���;H����J�l����v�R�D��=��/v��+&�R��$��M&	������ �d��������w���&����$��d|tg[�V�gk��v4��p;�D�� ���wL��S\<�6m����*:rL��V��[��b>h+r�	�M]I�{g�����l�K��b(�z�p �-F3���
I�vg�����P��g��[�T�j���x��n[<�Z���&�=�
�����X�u�j�� B�9���{Y���9e�ag�A�s�R���u���:q�'\h�<���{�M'�a��s��p^`�'|,,VFiDU����a��hu��t��@F�z�{��������3�2[�����
�&�#'������i�SLN3*�9:������s���0����V���i���j�������trJ���;E��Pt�:�\���#5�q��<�^�FH���
3�������8�5���E��	��C��s�Qsk2�s��S�r��Z@0�#�Z�����A<P���#���������Z���l����'D�;���d��x:�$|�l�f0�&�LS-�&�V��[k)��=���k�V`���Ukn]�N��8�V��7�`�=[�m�VTR��`|��_����d�Kc������i^E���.Q	jQv�$/n�a�vl[���1���
'�N����=0+�5�f��l����4�+U�;"\��[�?��������0#�v�`��A�#~���)������h���;�0�>\$�0FB5���Qm�q�fy������kC3b��8qbL%�����i��n	�KJK��Mc����E��wD
�B0����"�������XI���i��4�����I��j������m�������m��|}��"�nT�y��+=�.��wr���N�[Iq{-m�������YN���8��N�c����=8�l��=��[Q:��6��b��;��n�K�5�X��Ss��6hf�,,��+f9�S�b$�'�<�A���!�������&�������0���d�,�0�x��AK�U6�M�Q��/#n�`�va{��v�#�rsmT�n���������1D�q"1��@�����bF�M�#�5�'6!hv�TB!��L�p$7���O�CvA��[3���z��3��.Mr�`Xw�{��5#�P<,j��
����r��F�*�e,rhT6F]��@���-��E��G��@%�`U��e��t>_b���7&�"5L]����?-�������d0��r������JQ�A��h��j�S����aV.�J��VZ�@�F���K!'v��T�;��D��iKK�r�i)���~I�~>^����
�_�%t��V�<0+m���S�Bb�V��n�S����v>�*
b.J����SO����JedR9~t�i�
�dUV��F�4\r�VD8���V��T�y�����Ql�����(��K?�	{����M�r��,
&h�����9��
��2�����=q.}�&�N����s��yX�����3���ju��@��b������[���-�l?���
���*'��*���g_��x]��//�������x�����[�w�����@Yu���
f��op}NbWe����N>z}��/LL��C c�i�p���6��e�Q�-����%��Z0���)���e��$�����6���ka���_|���>�N�:��5�5;�G�sN�-�^_����j����[Z���u��QpJ����R1�����h$&�C����{J
���(�/��<�R�2F��f�&3?P.���Y�t�2�~�4����]��|�O�1&���%�;Ae��\s@@�>��pE.Tp)�zY�(`w/��aF�;�m�>�E��M���m��Yo�����}q:��"k��r���YK���)�~�-tCy~G��D�5G��Tb�*��x������M8�`U���.&���1����h���[��D��{��[Q��@�n8�\t�q��A�X�<������lF��z5���,�Fm��{'�������p����O��;I�����E�Q������;�Q��2��'��
%}�F�c����;�2�.X��1��T�3�P�����n'�U��p*u��*�f\��w�T����|�&������f�����/B/Zr�y�d��������c�e|7��j_snR}K�"V)����?���:I���	}"�D�F,�!@<��2b�DL�d7]_����z&���8�6"��B�L�f��D��2Hk
���K�����6�`�7�*<ko'���������S���Q�8-_�m�����l����4�oc:�rF���?���s4���{z��x{'Z�����	���g�����p~��,��8�rD!����� �#�}�������������{�O���9����a�`zkd*��R"�`h���Y~����Mf8/���[.��EE�����`���NF0���o�LV�Yl�a|�����9Md������� ������M2��f�7\��8����.��3���E����_S[>�����?�o3+����or���o��p���{u@t�������r�Z�x�V]����m*����HaO��_����4c��S8��;�/���BQ,@��j�C��"�;�f����'/b���Gw���@VE���r�
�;pjS�S�>�P�����	�P��c6_r�LN���z������W����5Ej<a,��"�������P����3���?�^,aM�\
��
]�3�3�<C�'����p;���CE�]�_�q��3�A	e�J
�+�gI(z����	�����M����?��������S����w �;%Y��k����(�%�c_�P�f�U-����q����77CP"#oPLg��R�
+���B'�O��K�
>Hv@p�qb��<J���P�;R�q������>R�0�/���%y2�M��������j��y{O8�����h���Q���kwFv��N&���s{�y��`�0�]R�g_t
��4�C�*6���_�h������0V��EPD���#���`��&�~�����x�j��^����?��B*����U?bgtC52D7G��j:���k�^k/�U���$>����������J�,�"����7S\��w�*����?�����������(u����T>p����	�;b������h�VR�Sa������_o)���2EZ
�����{ �So�������t��
��4������H����J�[�75`��.�AY.)>��H�������[������Y�+I;���u���Y����_F�������x�L��&�.�_��a�|���%��L��#-��@7�����W��~]��yVB�w�bc�I��
�_�Z�\���}[�0�=�������c-r,���9&��/qT;G��`�G�� ���<��1���d���`|#����|r"�vp�-z �w$F�m�c,R���%��
C�'���;_��*c
�^r9�`,}��V����-B�~��-�+G��*%�^�B>����2������;����e�2��������\��0h���xd��������A"�����%���N��c��M�Zp%���3g,!B�*�}��d#?���wI3Sb�C����TRQb�#�|?���:��@�x��DI*C�:�@�Yd�*�8����4���-|�,|�h�8��roC:%,��pj��g�x����#�R�?��7�"x` ���� ���7gL���5{a��Lg�R�%63F-4����LQl��`1"u����]~c���LC`�7�<���e,�/[�3���;�S���:�*����hI�����{�$���W@W����=�������ut���1��w��G���A�8�%6��w������Q�5R���y�6�@�����NE�� ����g�\�.}�Q���$c���
F�����8��@A��&���%�K��co�H"� p��a����#+�E?w �"A�P����l�"�|,��������g�L��
�/��s���O�y3����F�{���\�d��_��c�P���>��VBA���'��P���
����4����K�0���������;Zq��I�]��q�zg�����MJM�g��>)��C��].���H�Ox%�!j��00J�<l����{`$GI@�H^F	��b3��O����H�����O�H��+W��_���u��S���_��z����T'��.�!��	��@[X,��3B�L�z��T���~MA�
O��LVi�H�a����I�����Rld*/�z�>���+����	r�K���-��#d�09p������{rk�>����-�bR���Hr��T��l��C��W4����^I���B�i	���/z�0��p}/^:�G���?%;1�?���\2�
k��G��v�S�%�0@�/$>}�����t5<E���u�>\�3�$��Y�C
[�+����&��������5�Z&3�!Y�$��-ZaOj��iGX�28��rO��>J��c��\�l#�2^i�#�8L��A�E����P�K���;������_�	����e�����I���<pY�
��z����=Y/S�>��O���-��X���%���7p��9(�3�e�z�����[�"��:[[��d��B|����P'���[p����:����O�t%��
���%&�[�\��Z���3�s�v#'�g�������x���4�����Q���p���&�'Z��h�,[��h�������M�-*�Z(��1�^��)��UbU�9�����i11�+$����B��m{0�RTP��"$L��$��Y�0����]/o8�r�������~B+����
t3{��`G.v��3�w�imT5SYC"�T������nF?�M�g��*NE������&Q�['����o6���ES�5M)��S�"j����v\�8�X�|y�
u��I�W�+�\^f�#�������Y���i�Q�-:%��"�Z��`�k�q�;6i�J�=�c������r��=�.H�|��0����\4@����0o-P9�H�����vV�&Y����l�S���2�h/��nBKwCN��A%$U�<=*��x��2����U��|V�.�h@�Y{�M��%y��	������c�1y�9��s<�7b|�?����)�#1��6
%�T����yx�|����WB�����0�O�����F�zK�����3��HN�pf�x:��x��2��p1A���lq��]�N���D�p���/�g������q���q��:�I�Akc�)���G��HD�*G�Hy�!�{���K
���<�3��0�����4���t��`MH��f��e0��SgK��8Vi�<�t��u��
1kdzJ�46p��� e��~����}�s�����k��8�^���xp�?����;�BL����-�Sq��zE�-��%>�g��Bl�v��&��h�:&��zDg����N�
��Uww7��
k!�j9�~����Q����fYT$WE%9����|)m�wR/>�oa����0�6���t0bf"�P������~��!.�;g�b����_�����|`��nbI�T��YSC��[bh����{�`"Z��d�Q�)���?d�Y�����A�^�iS=��mD��BSH��)f��MX�3������r:��S�%�avgY�LPo�D�R�`���$257���:%��wU|��/�Ao��t;����|��Ie!!�����,+d	�����o��d��
�)�����������E0U��.�������*������
�3P�;�[������f7��}"��j����I���C]��18F.�F�k�'��!m�<�}+,l_�; �Z��:���'��s��<#�����+
U���XV�i��\���iq��X�!R��=�F����-q�e����-����^J�S6���VF�DJ[z�����|��eX����(���T���Y�������t��=�����
!K��
k��7��j����J�D�!��9�p���H�wD�\�*����rD���UK~/zDb����Hx'3)��P=Mj��}o�� A��k�\>D*��B+��
�U�T#8�].4��@���E4�`�0>��M���V��+7X������[Hf3�P@����e$O����	2e[��W�����E��;�S��}=��I9%P\�`d�2�N�@��?�����7y���hPI4/�u�7����A���A[�1uW['�rH�Q�YY�0��z����h6�S&A�[��}�709�b�����;'�?U���m?>pJ������f0q�Q�/��
������^����+��o+����-}|����X��Fh�bgIE	����`l� !&��|����r�$����wG�L_��"�+�	����2b��2�~r��L��+��.�Rg��W��_km�&*|�I+�����������|%�P�R��@h{c���o�E�M8��������)�?�W�<7���-��d�UZ����IN���$���F�$i���]����X�*������-�)�����`�<O�_f�@����0��1�En9)5R����yT:gth7�.��������{�K���t#��P7��\�"T����7[�u�D��i9H��{���i�8���(��2�.D��0��jb2F1K�Ks��C�t/\���$8�k��a�w��3:Z�dN����:�D�1��y�@o���i�V�8&E�+*i�FP<�0���7<�H�pD��Alqp������h_�8U��C9VW@�&��&��JfT�f�;;<<$�+[�oC��p���L{����9���#2W�4��V�r��{���)w�N��^J��%Q.� "�PM[�bK'�%H@��N�g~�����+��[�u�_�J�l�
u�^����7�Hed��w�$�X��8���wLK�X�m�/EC�xK�>t����,�����''��a����N.F������[�
C
4���3��0c�CB�����:n�<��F�7M���2I1�H�dK
lF��Ap����J@��M���9A���3���=!�I�\���L��{��,]�xm��{6���n����EJ�������\����
���mX�W��[+��L�v����d��
]�X�K���)S��`��f3�~0E)<k�w6��n�5�)-�UZ\)�4ua�W�kdp�U��_��L���%T�����;\����5@Z+'��H4����W�A�����5�M����j+���?U�|{�4�)f�Z�ft�n&g�a�G�$g���e�2S����W ��kkf��[o2����`��QO�e)I��Y~�����F�I���������0II��jU�L��9F�_�BsO��?�z��K��$�����pR��n�k&�G�Z�n��Vm�Fi0YS�?&�rs�oNkn�Z��4Dr��7T����!lJFQ5��S^��lb��N����hI���$�������@)�=L���%��P4��!
\+��>����#�m	��=�`O��
1mAO�PT���X�!�&7V�lX@��a��pP�G�F]�R���n�Y6�w?�>%����&��|ob������(�~�V$d�
y���.���6C�5x�"��2��
E����m\.���(o����y�){��_j	~����.]�{t2��zL>T�/�$�X�`k�=��y�a
N"L�{��i'�!H�7��������A<_k�7�+��l�B�#*y#�#�y��$n�����������E�Z��V����<����_p8��B�g/Z#�a|/[�vJZ�EiS,<��:����a���b����0���_LMK6�$P�����D��y����b����6�<��j��sh���e�yf0ryxB�m�3EI1��z��6*z}�'���E�n����������\;j�xR�U��d� �?�-;Z��,�����f3���D,VP�uw��N���D��x{� Ep�
���JG��w��U��0�Nur�vMwbz� UC��H]����;�NB�j��Bo/py�$����-��%��[��`���CZ�J��U;I���������<�*��*��ag
�����0\�N����x����-���X^�\�G��G����}
?S�Q'/�K4@��}5WF�M���:�������5�V)?6����*��k��U�eY��R��z�f���d��i*<�3��o�I�����$k��[�7c���'N!1��P������*U@������:���w��~�}��sqa��r�X���,�+ue��vk��v3=�4JD��[��Zqk5+c�!�HD��Tvkr�0z���s`���"��p��BZ&	�[:���b��x����
��SQ����h��VY�.1+��)��y���n�]���[�T��u�e�lGci�B�no����,l&6p��J��W�	��m�(��?��TA+~�������#�������f��v���z��*Xt�� �������X���'������������_��������H�^��Q}&a��Z~;�I[uw<='C��2)p���s��A�VKq_����>�����"����n��F�m���f	�"�s
���R*����O=.�E����u��g���>�����hxq�?� ��O�'z��b@�1d>K� �f��e-e�)������������[�����W�?5����Lml�kw�����kiK���DvKltG��ZU�.�VP��y��� ���5@����yE����)�,r�K�l]q���m����*	�,�!N��1N��Y (�c�����H����W���l�t�~c�
���{T�P�'
�o��i[f��gE�Xb9��h�dDU�
���=K/����^���$���
1��l�_Y��O��������i�6>�����(�'��Y3��+�������U�	S����]�BRz��l%�
 �����R��}hA����C(�xi��V���K��(0��CX��t+���i����yZI��C]��06q:J���.��i��JC�m��<�����x�<��lEg���*��[i��&h������B]�k�-2�^a���"�~
��}��v��������W���R��V���wi
zf�5���U��2�"{�����Q��r����%������'�q�Z��Y�g�tqt��������.!
��\�ri�>�O�nVhHR��B
��.�$]��&x�������!<w�fn����<�gHb5�:�X����B��
y�=6��r��������V��7y.�1r[�g���u�Z���g���

k}d��� M����Zukq��SO���Q�����K�c��B/e�U��;n�F	pF��X��J�o�k\��M7����9�2�k�o����k��FP*���>o>\9�f+����,N%���k�o���`��!���dW��`S��2\x���`>N���W�8�[,�����u*������,S��w�7��_\���2�E���ZNC��n�U����p��/G��2��_������CV-L�)n������M��*0k���()2��(cd\0�f�v�;Z��sG6�O����R�juXNM������~$���N'1}e>���g&�����=l}y�����Gke�Oc�Vn��zvnf�EI���S/�=������i���cor���`������G�[jb��r���3�(�G:�oRo����F�IXSi��J��dI��A���]��rf��
�H��>��If4�v��,)B�l_����0��r�1�'b�7�Jia�#�*@�E��XC�Eim�K����<e�nS�1�.c�����w��S����b}Z��|R*a,s�:XXH/{��A�`������bR���g�i����#���W�6�����Gn�'XRl���6C������H`�����tM#KV^���+�F��`�"Y����3��O���r���Kk��N� \9MKH!)�D�90���������:���z��/��73����Pj!�r��p+�f��BS�������$�f�e�8�������hj��.N:/����������������&��$q<xz�������m;��B�1����_�y�.�`�7^&|�+�����GS�����AdYV���Z���B�4�����
n����j��[�$�����o�/A�p�r��uDV|�@���@���Y2��Z�e�N">4t�I��\]ui$�`��)MUu�f�MJ�Q�����
wr�m����A��0I��l��oY.��s��d�:�@�j�������zi��
%`Nek��o�k>x�a��<U�\�n��h�<n2�wry�S)� �J�j�v���Nb1��Nz��rm�X����u�X��-B���Z@�"�^��,��C��[�)���8Z����E���Y���c�8�ah
�7f���O���
����o�.�x�������(fi��(��:��i_*sF�l���du�+���2�����n���,�	�UoIr���!(��vm�����`����"s��f~n��l#�Q��M��|ky%�D�w��N?��u��r������=�������f��������t�1���/z��y��tzd�����y��u��Y�Xq�=������M���	Ujj�?[_��p:�d�jpvt�m/�w?�Ohea6w��HH:	"Le���wp��lk�L��&���v��j�>#���T%��Z&��s����P�E:�?L�]�e9�����z����NQ�v ���<JnW |�����!�YV���!5"n��E�r�?R��X9[oQ�|/9���2��]���A�*7���������Q�����
�����4U���t����7CiU{�Qbp��}\��+3�X���u<�H'8{�]�/F��G�������p�����������a���,�������r�<�wB�!|��e��T�0�;����F���B�<"r����[`��+g��A��P����Q_��s��L`=���4������	�t������&CU����V����?�j�H���A�v)��l&M�e��&�U��)��t*��j:��HU(N�9�M�*g���K��,��cU4z��Q2�9��'QGw��Y(��3��oyT�W�)V����W+��u��f������'�|�������i�z�i���K���j!�[2*�&��I����&Q
��#3�KU���[Vo�0&������Whh���v�����������.����wN5G�|p:��EA����fX	`z#
l��`�L�QU�@��z\����v^:����Q�������|�����3Q��K���z7�W0��W`��M��s/�S��z�	C�-X_C�5������T���d	g<CX�=?���i(@�>ii4H{\An ;d�E:���S�1&�B��p#��6��U�"`�fK4�2Z6��zv}��Z�^u���������:����[��*J��C�:��(��X�b1M�����&����VQX5u��J���T��/������Z��5����,�"��z3�/�R��~oU�e8j�Jl%7���	�G�c	��j:�V����OU�����^-��xAp����Z��]R���Y����@�y�A�h���e�ztg�%7�\f�R�'�Z��C���up��:J����x�8����^�n}��,c�
6�)���������w��7D�f@e%I���0�w�H"����)!���|�6"C���j�(��
[h�
�@��1c� j�Ur�UAz��h����I��lY��2��`\-h�p�:�TX+�������*@�4�*:��q��=�����\+�� R;�=jJG��
��F-��:dx�����a-�W��P�i1���{��n��1cU
����X����K4�u�zoN�Dng�D�;�]�&���;)Q1B��NY�d�6��n�C��_���a�x��}��S��x�zm /I_�#���A:k���U ��gO�{&�5��|w[�0���x�:j�����v���S�r���n�\����DKz����2�,w��Kwp���T��2�2kc��[�[4�;�MsL�Y�u���fC��R���t�"�\����G�Mt�8�E���,H��
rh��:���A��%^�?s;c< @��%b�3j��-+��<�T�0�e��u��/mkzz���U0�(���{tr�C������b4���w�eBz���I�����
���|�=;�����(����7��	�!J�JZ]M�#aQ���ty�U����~�\?����g���3�xO{g��P6�����!5y$��\�Q.�������6�W�l���c�.�NgKk�vmLk���P�����F�/�BW[���w�C�r�������bX�R�h ����D��]�ts3���tn�	uRE������H�W�n������O��/��']���D=��@�X���H�X��n�(O�d���T�F+�_�T3�:�Xd	�
o��6������G��]�p\�����d%V�%���2JgTZp`���H��[k%B����S�H��<*��P$�V�<<���qh��x@��H���U���q�U8�e��?�zNdL��r���tk-�H[��x����
S\�u�Z��
A����������;Nz�)'7+���f�s���2��Z�����3C���
W��[����f���>�UZ�D�Z����|��&��c��
���Vi���1�p����@�'Z�-�OQ�h�5���?�J����o�E�s�)���?�ex1�V�Cf��xz������m�^����2�����O.����R�b^)�x�v��E���,��38?�]~�����J-Ev�M�	�,����\�����+���G��6 �n��E>Mc����F<~Nf�����������&���c�����\*Ykn���Dv���;U��v:��Mv�:�z�������19s�-XU+�m�m5�M�Q�>��z��l�s��
��*��V�S@�����#����f�k�Qk���~��=��n��n�m�YL����.���^w���������p������B]�����b��/J`F�\q�f��F�h��f��cO!�������DYF�7]S<����E��������w�EX:�N�(t2l	*<�����l��E�V����	�>���q@��)o�"7'���j�5�N��&�����N3W�g�?�[-����%�Bh�-��� ��s���q�L���P}��d�U����� ������W�	%lL%Y�s���=�^�:�Y�i���OK�n���_���O1��l��S>����?%��������������k� ��v���v�N-����0B�+s�6!(v���n����$`y����N;#�l1���b�Mq�d��,���)R��^�?,�r��V���j�=Ue2���<�?�����x�c�)�k��N^��r���J<~.��i6���%�F�vB��j�Ji�R�n��m���l4�sg�Q��1j)��N?J��Rn��J��.�#uY���[.���ow$����\y�9H� /����Tm��vj���L��m�/��Di�����3Mp~:�]������	��1v%7��R���2w�AU*�_�?
�n�x!(�z��m���z�feg��������'m�[��J�o���t�n%����y�Lf��
��5��'@�#����/�)"z�����0
���#����IB���-oS.�'��	����z�	!�+�IJ�nw��!��x$���X$���������4���}���l�nK�6���gS�g�,2U�l�[.s�T�qk.q�>���L"7������8�0���;X6����	G��}F�|����P���N�^2#T��]����8�+�V���	�������Wt0a�\(���v�Q���,�%����8�;Y�L�;-�L�����8�k,0���v�5`��F{[��1��%�KT��h2���<W���FA�00��iT��?$��4�"�W�����t%���z�����?2��W����wQ�F���5\�N,�p�=�q������38�9D@��fK�/@�2	;C��J:��Q��u������>Wa��+`�]$�����z,�@n��{�&�g��a�2��-��u;�@jV2c^V@����-C�+�U2�������_�sei���ZR3��|^�Q�d��������� ���������DT{�+;1�o4��f�Sov����sY���k�����!��Z����
�2T���#��W"m����EXrn��9�����KY�Wt3P�E�/	�]��8���\���d����	 �Y?��@�N��m�����]�8��s>�y�i��\$������?SQU��c	�a�K��_p]�Jx�I�|�������zX&���3���w������r�yUf�(t�k��
f@��e�^�LNN�f~��OVp%S�RYq��
R�d
����9���yP��s�I|����g?Ig	�q>]���0^3Q�q�k��^��W�/�6���z�_#��VA�s0��w�71��jW��:�����J{6�8<��K�tv��v�HE��YH��eH-R�-2��?b������gt�uf�'����f��6#����r��M\����NYf�����x(15:��2�BR��� ��8�����0i-����be�V6re�W9ks��9�*H��D+M��d+M�l�+�rmB�
����+�z!_)���W�dm��L��r�Z�+���B���
�}�
����)7:��,�����"���$Z�$�*#e�����������^v�&u�b���V�
*�V�{D=�s�d���n�Cey�R5R�l
G6	���Rof:�\�N�{���QOw1��S7��l����(�K���S4!���4d�:w�*=��|�����z>����'�0�$��!m"�����jl�5�+��3������N��V�G�X�H<}z�g�!y�:�y��m����nn��8A�QZO����h��:;�V+�s��eoR|��z�iR�\v���(5;��&�MB�v'���%/�������&j4w�y�Z�?+*@R sq���aUX�5��q��ntlS�o��T�T.���8����fx�cA�tv>8��e�����S����yQ@�n��!J^7�5������F�#���������;�5��q$C������n�)�S�j�\Eo�X��?c�6�_��q�=�@"���j����.g^�H�Q��d5Ux�.���nz'�gM"�,���Xy�!M1�&c���iAPm�!���P�_z	����G�F]���w��E),ug<umM�R���E�������r��j���j�)�����ZY���5�OF��=G�'4�c��7�o|�Z9j�<K
PKg6�����ixPb��J���.����LH{{��������V�Q@��;6Q�>��m��$��D�H>���i�� 0LU�X*���P�#�Z��uc��=@�����y�E�R���8�F���*��D��?YK	�p��(�Qao���I	��tZ�[��p��"_�-��j���U�n�V����s���siV���������!�����r����� �����������C0�g�rH��8��O�%�����`��ZM�IZ��&X�F�������S?���rT����@����w�]v�-�3��!��W8��_)��c���J�i��
"��Z	M�i~��L���o�;��j���l��������Q����Z7�=��qi�}E�h�r8��^QRib�������v����zT
I�3��&�B�AZ7�M������s�.ScT:��^��%%�d<2�1Zv�l5#��<���.��r��F��N3���6�"�z������L�mk0�����$��g�"�w���Y4C-!V��6��
t;X��=�&�1V������X�v��v��P�4�j���0����F����o��:����@�
����5��0��f�
XRF� �3��J��U�	o.�d��)��`E7��?�>�z�O��_���?g�����In�2�{i�*��o���g��T�����u�r����:����ZTdK(���p-�%m�� ���>��,�����*�?����o�D�B�������~��5��K���F���D�%p�\�</}����*�mbT���l5z����H�7w0�g\\��2��L	Q�0,=�(������@����g�����-���T	�O���w�{�n���������>�n<vE9
���n����4�Y���_�	R3�*8�)z#�&>o�AnB�j�m���aw�^s���x�:���y�O���.� h����2g��g�=���Xu����F8�(a ��,p����CR�H�5T�Rw;�
)
0�n��*��i6��#�C����W�	@��!C>k��7�"<��*X|,��?�H�m�������zp�p��@L�����#X��'���=�����q�{�P���3�i�5��T�!A���V��H��TZ5�<�e��M�I[rNW��	Q��E�{������/<�='����*���i�Lq��mL5!�;S$�Me�F'x�c��&]�zr����o&bh5�oh1hie�d+D_���4���f��~}�|%���4�K�$a�K�~�*��N�#{��d�LRH������W�}���&f�X������qJx+�o����}�s�����A�]`�Rz��	��$��6K�1�|�)8��3�|�����#��|�|�����K4�N4]'�H���L4L���n]0h��8����DM9JI�({�n��y�d�>-��pt1�/d"�1C���E?v�.�h(�$������'��Z�o9,��LU�oM9�h�����x?:����A�l'�PN��	�x9���D<<%M'�q�p�GK�6���$x%���X^�,�89%�?��r�D�@�[���<`&�:�y���!�R��g���_}���m	6XF=>`O&�����i�fl�m?iK�<L��k�h;b���#�G��g�^�BI�[��r���A*��6G���Sj�k~���`��++(�i
& �
��#�$�����`z���nC���/�A"���|:���I7W&�R+�G���.IS-��qKz��iz�
�6�o�8I�O@�`���b���Q��Z���
]00&`�+i����/��������z�
\)=�Cl��A�����N�mt6Z+E��	���n��)k�)g������9:���w+��8�QlyL���J:�IbO����V�����c@�Vs[�F*1f��.��m��bH� ��x�;K���U�VM����A��������@2[\���#�����D�WY_<�Q�,S���G�������J�������Nv��	��XFVC2N��Q�<4P�puA�k�^�Oth�%Gx�-xq7��;�s���n5MU`�������O��������!�?�Ozz��r�^���Q6���`�D�����Sd����H���]Y�\�\ }��c�����H4����^�Y�Tv�r���Zz���������//���'�	/��x������I�Qd�������$�������b�J���V�v�`co�_Qf;]�^�"���p�ukV���K���/�v��-Fk�6��3��[ ��*{���7���/oBy�#��1HM����Lv<#�^�(o�F�m���Gk��a3R�a�Kib��!��g1���?d�jp��*aM���%��\����=��s��^W�F����I�|��+Nob4����P��D�I2����V�p����I��� ���O�}Y�:#��ExKvi�����r+��M�]�l~j�m��{������+�
��r��������Kk��R�XnL���tq0�f��4e�'_���{x#*�u�S	���f�m$�\��Z7J0�1�-��	F3����f^q������y�B�p
�g��nm�0�V��g��D�I��w����)�X����������N���b*i���Q�����Q�4�*����qnW����f:�u��E�C�s�Cw�lQ��|�M����K��T[��mr{U������Pn���LbW�6 I�\y1�V�;#�W":R��K"�iV^���G���r]��;G�'����y���I7�]AF�����6�����Tk�Mw���g�����g�[K���0#d�G�fj�v�SB�����B�J������*���>V��e�*#7
3z���/��j�U��W:���W��	\�����W�x�,y^(}V<�s�w����u5��u�6���q�Y�����A�`;���8��%)�b�
c��n� ������lc��5w���97-]:q����b
���D1X�]`�ed�Y��}�j�\w��J�\ni|]�|��y���>��qBq:����H��x��n���K��F�;����c�����	?c^Y���-)��(�����'#�����N��(T�Hl��Nr�e:�v^��/��mC�|`�������:�n"���z�{�c���l�3�]8��z�kYk{~�"�5kK��������E�M��[�����;u�1��v����t��H�9wm?���Tz��m�&�|2�v��,z4�	/��\G~�������2w���-��OU���`)
�"�y��
nu`���$���K���4��Dr�V�����J��@e��y��J�j���5�_?����@��JG������),@
��JJ����b�5�b���R��q�k!�������I+k�����yd�Ofr��N��6�	��4[�V��z������U��F�����BDy�o��4kg��j�`��:���i����?T�#/�F&
=@z�V�lV���V�-L��J�n���>|��j����z$������Q�$UT;K	T�T��95��Q�������O>e2���3�}�����hD�O���6�Z�lu�K[���w������u�v�%)��o����X�$[Y�����Nn������&�j���y��3�����y{��>�)��S:���������n�V�d+��m9�*���|��W$�����_q�'����Ld�;��e0��F��V�7�"(��-+��#0�Ac����������+g�I���g���F";mD�"��.]i���ty��*��Y@�q��0O��3'���L�h�R^�i,���BQ!����n���N17�Y�i�#��Z%*\j�	X�f�u�(,���������N�O��%���;,����W���(>��>��k��OE��->��:���/�9xg4��G�He���a�����N�J��fD�A�5�V���~��+�N3*`�N����u[VBB�C
�M��Z�������g��b][r���]j<h���A�.���~.�_���fu����ie�H�lP3���#N�H����[w�Ywk�f�Nm9{#E��8��H��M�	�XV��s[r�q����Z�	��X�>�vP�u�,`v�
���U�+�Lr��f���+5�^m���#��
k�*���4��HV����Tik[��V���u�^k�g����Bd0�����X���Y����TQ�U��P*
�^a��3�^u8���y�����Y�\r\a���Zn��	���@4�va4���/fc
�;q������Y����"aJA���)q�7��,��r4���m4��V��������_��t�ri9{���������\
���{�[����L3o/bA����&`������Z++�t\I$��O�+�'���P-o��ip�����{��\E7T�H�J��������.���|gTVm��2�z�`�]�I����~B[���q��X�T��`6EMU����~����z�eFK�������*�MFr��R<���=���>��CI��
��P�dB��OW�B����������i�w�V�}���6��'�n{S�H�,�'2E���O�v�����
�v�!���}���\�:�T�-��MK�����W�E%��<()������Pd���:��Dz�y���?a�>�$�
�n���4�f�9)��?/���Q�f5�V�h�����i�3H����LA�te�M.�I���sy���U�_�a6�O�������'���^�1��#�T�q�2��J�������jQS���'����zYI�����y�>���t�jm�e�h�����;�l�;�d��vY���m���������j��U�TdMn��W�NYqFPF�NZ�o���*��	�Wv�:�	�����*YIZ�*IJ�[��g/�+��6*�!?�/��F��#���L
^������J���z�$�5;n��L���$X�Fs}�K�!�y&:\�x�Qk����%y������{W�J=*�a�4����t�,K��K���&�F&���S��xR���u�B�Yv���slH��S.��J#3�]������������h��)j��L�=��2?��w�S�|Wi���$r���i�������I�$��W����b�*�������t� 5���c�^�����
y����r����������rn���{r�:��j������x���q�}��w<|��zG���
8���$������
��>W�����oH������Vg�d�7��M���wr�<�ZL�W���j�r�����
]�U������0���j��6�|`/m	Vr���[a��h?�8�.>�����U���|x�e�����>�BI��h�M!w��I[O��B�P��+w}�-���f�����A��3��n�Z1B-?��'T�v��Q�!|*��T�%����ai�Qx5Z�p[��x��f��e����+�$f����jA,J]�/K(��f��TU�����U�B����?��������n<:�����;���I����-�u;
���E`|Z�e�����"��H�����q4�(���
L�k��J�W�Y
��m��m��a���nd����3����D�� {��`�/�18n�a�kC��#�%�����U7N^�4s4K-7�������f��,��?�M�<�������#*�/�0l���/�d��_X�x��x4������������+��u�J�M~�U���1P�
�R��t�D���n�����m�+�#pdA 	��<����e������,:4�G"���B��+�Y����!Z�%F������u��K��Xb���O�,�%O��'�u��Z�~��-'��B7*f������FU�	H��IpE��3�`��jA�^�+:B�j��wz���j�D!<����8w���0���]���B�a��[=�	���Tt��[��m;C�
&1��9��s
�3���8��E��w�����~��m9�9���a��������sV��V�������v�����c���{x�A���Zki��'�s5%B��q6��*��US�tL����/IN$��:��X����N�45:����8(mk�E���5T+m�Z�=����6�4�6��)��D3�`�����s�O�"'��[�����G��/O��xAx�j�
�G�Q�nc��XH��F�u�f�j�)�s��tJ���-"&V������$mv`��������}�$�����Q��2Qy��f�\?X����������0`��ZE��7'��K{�}�v�VV�� l��o)�ES��+Pt��{���;����L7�]rq����c����\���|.S�������1p���NiWz{����}-�t�n��������m�(x��N(n8�4�*(���D���f�"f��6'� ��>� ������n�5����A�-��vk5
7.vw-��w����^��(���k��H|�/9�o��,����������*�.�Yd;��V�S��V�-=�P�Wj�����w� �����_��?��'������7M���x�n����lBd�4\��Q��E��y���"�����fv��Z8p�V����s�G
�:/:A�����bD���9��������E�������c!,
K!/e1��{��O�=r�~:;�_@nZ���&��q�	+j��`8��[�B�RN��.�+��m�"�(�\���F����p�|$�E:9]��o�����UT����������;������r<�H"�{��W#X����^�"���#AxDy���@�C�'��'���%j��^7�|�"��+����d":n�-�<N:�sq�'3;X*l���y��&V�0Yo<�}�1,$���c�=8����8�������	����.	���L��p�zl[�PS�i�V�z��xi|�����r���[���`R*�4	'�N�@�l�Z����#�]��Y��Ma��6��9���0���H�������bwR�ui����������Z�V����9\�ix��u�.����o&A�Y����������Bh�W7�XL�2�#��Onk�]�0�K���0�uM��it��,nt�nS;Y/�����>\����������Go����������t�����N�m�+�`M�e�V��T�H;�Z�-�l�K�2PcC���$	n���X`�$�f���pRc�	��%I!(��fY�����^/C/Z
�meI���y���ZH�6��j�H]%\0�v9G�d�(�I�_�Ty���e��RUV:������s��$���b|XQ-�9_/�����v�g��F����\�@02����a����F�	�6e��/���=T���N���R
}F�|��^�R���������j��.M�Y1������7�n��q�*�Z^$�	�K���K�[�"��/$HY��:KX��2���w}�S
��yO�1�pl�m8t`�7�"@�����|���S���������F��������'���!�0{c������K�N�K���t����9��k���������������o�����(��S����
0������X-�`��"u����Q��B)�����j��n�^�=��������'����oT�V\tco@x��L�#TG0"r�Nu�^Jd8�%]�	w`�����:3��mFSv��)�����|��������S�K�q�m�i�� �uq�;����"��#qD85�6�3���G(�����g�v�����t�r�"���4d�/�����9'!e
�C��qW����p}���l�7~��@����;��3nz�5�7���C��x�^��v��2�R�����]m�m�I��W$�q�$|W���7���6����i8��J�?4�M�X������$�	0�K����t�<����J�M�Ip�����!
���V�#`(��}Z�J��0x7@�P�R�X��sN�+7f�2&������Uo����z���MH"W'�c8Sf=X�!����KD;7H%������_u��M��,{\����L�.�`>��q����z/��K.\��r�����[�`���wN�f���7������[
��a.g�k��.�=�z����'��R|��f�J��V*u�&�\_,�J��K��d�-I�����y��H�)j
�5,�-�7.�+�n�o���KQ	f��#IK�wdi�9��O�{��NFg����p8�t�Z"}& lliW`5m-���g�������U��.�#=�����v���pG�k�5���Mt�U`�r���
G� nD���
�'O����\o��N�T���h%J��KU����h��]O3��T������k��8o���&ngKcI��|���M�c���8&�!�a���,�'�<~����g�+�S^��\(5W��jP>��q Q�*n+��-�c�m3����a�\t7[-�z6b9�.{��W$E�_s~e����:�
 )�f�fK�*����,3��)y��.�n`�(B��D�s{on'�2}��g"�#S�!3_����
:(	I��9�������]z`�$�j:�xt�>wjn�^.��=��9Tk��7��V�fe��%`���Z��7�c�<B�SZ���X�i��k[�'��E�$��JF��E��&
 ����E���4C�1R[��P-��w�������^�(���W�+�(������S�JQO`�A���p���m�5��&��N4P�tAO`t�q_.{y���I'N����n����o1���EI������/h���^�=v��F}��h���/'�>�����W�e��G'�������ja`��~�%?�Dl����E���5_�J�T���=��Jf�0�A�??R�S��A�Rg��O�,��y�c�$-�� �E����?g{�^������!]o�e\78��M����bk�^e�����E�:z�kF>�5���3o��9�;���`�\�t!"�7���;�u�9��~��)g2���y]t�?��%���tx�S���[���N�H�hh�GT+������N��������P��G��B��z������U��D�!���p�Y�0��	&����8��
�i����:�k�,;<Z�d�Z����@���}��#Nu���(=�5�qr�����a�^�m�LR���"����^ `qj���.z=)����i�.5/a������0�G���H��H���1�1��a�pcWp5��M������1���]��Au�H���"�d44��h:5��pEa_(���G8gR~�������\u]8�
K�s8�Q�d)�zxx�!�6�x��;@����Q3v���<I�&r������0�v����F?���$���i��5�:������b��7�?��D��Yn%}&^�BY	�]�Gjx+�k;"7M��7ke
����������s>1���}U�����$h� �[��9����5��u=�:p�P��%�/tF�dp����q��yN|�R����}&����w�������#4�9f��q��(��1B������ACwF�oB,	Mu4�z#'rz��c!���@���"`ro��14j���|Q��G�3����-f�%P�tq�D���|��r��fS�H�<1Y�,Z���q*�C�;��^q�1d#.��`��"Y����q�#�|,�r^�������	��{�D�8%o�\�R�]H��6�����7�GtJd����t4���-�7����,�A�y��G�P+N����f�N�{���4�J�T����fQ�&��t��m��s��Z
Lc7,)9�n����i��!���w��&���s�,�&h������u`b-
�HT��"����t/BH���Ew���.�%�wI[wm�1"Y���T�H]���d�G�,_�����?�
���r$��*�g,�	���Q=�>�hv�=8B�RS����Z��bq���3:����)
�~L��1�U��gs<A�X�N`S8���&d�j�Y\��&o��N����}����wPFV�.�G==��dW�:��cM��|�O?8�}���'����Z��
���4N�Gs>��u�����B����K(�z��K��8���{��g������z���{��i`�(�G3����F7�l!��~�Us������ri����5���s<U�h�)�g��a\���G��	E�:c� ��E���D#>����;��2pS�i6p��,B�-]���V��v[��f�Y��gC�N��r;�fJr��iz������,6w�������g�\��+��4H����S����,��W���
M��5�^�.���{���xu^�rgKx��E���8��W���D�F���cuo�p:9%���L�7���2{w����:��`T�RJ���F	pR'����_�����6���#mD�e��_1���������>�5��^��p-�P�@xk�YzD�`%4Yj,�$��s���WK������rK��"?
e���tqp:����h�R�����������m�Q����i���v�
��Z{���I������!�(�I
��-�)��`Y$|��D�>��,�(�J��l�Z�d
�Q�W�(��mX�w+u�hiRSw?E3f�r�Ts�D�SL�,Fi�8��
d��;�x>F�`y�8?",o�Fp��R��
���E���x���I*�
���r�Sv�_M�yi�I�������q}
��*%��V5N�?k���(��y+�^^��63��$3a��ty�brF���Ze�	+f�r&$	g�����uG~��T*��iG�6��g^�)X�
�^����7����������p�9�����4����g:�M�l�[�%���/�'O5*XG\E��W�8�@�5�	��Ec)N�����|Q~^J�*������3|�/E�������Y���:�q]��@�����Z�t-u����]4Fd3��1����g�
�%k`l�v��)�/�;�,��
f�Ds������ ���:?��D7Tl*���	����F���5�B������W��q[f�����A��L�3�+0�����u0��v��P��sb��&!��E��y���r��T+�5��rs��I�P��I�^��Y�q�+s�����-���TX*���b4���NdC�G���{��L�m# 4��N���*���jo8���M���u�.*�Y��i+3%:u��?�ic����:v��@te��@�����%�X���������bq���Q'����K!��xQ�Tp��E��V<�5Z�w*+�G�&�p'3\��p$�e #�[�o
�?4Z����f+���3 F#�9�d�+�P��
�o��*�af�^�Z����`*�Ly��kEf���g�8
U�!�#�v�T���{���g������u����$���_C�������M�:��Rl����^���LJo������	wbK�d�([�jo�d�������fpbG�:TY��i�|(o��)<��_����h��4P�X����']��������:o�^��s��(B�F��Z}��k��V<��2{<����V��Z{0����`�cNv�y�C(��e�7PK��M�d�����U�\aLU�N���E���%�jg�]k ���\�O0�����!�FC���Z��^�0 =(�6)0���6� ��M��[�%�!�s�)� ���*�
���ovOT_��I��Z Q�S����(�[L���t��NH���X����6��L����k��/|�m�q[�}�`������#=�5�����~�DS[������!�*�}vIX��������#��E��15�n�����e���g����5����I�EL���q�:��r���B�b}���p���
��+�����a�����k&�z��'���`��n�#�G_�Epu?���(vE�j������V��,H���,��8 ����/�H��:��s:��q�Zu�v�R`w����&m�'���
b�f�V�mh|�ewI��[�o���������o���q��,��s1����O2$�F��6�[o~a!_``&�_�hh�/a���3!�Y-��ZgC�F��j7,H�
�lk��n����J��n*6��B%���n$Kn��L4�{)H����@��
��x��W ����f����D���ET���&$aK��:||!�����)�=��5��'>�4	v`�F�p�4LU��T(-��DF3��M�����
i2��U0s���Z����6z�����) ����4�
���������S<���������SI_�����i,Z�����3v��z�t�i��nK�����]x���e9����Qk��y\��Qm����[��������pU�^�}z�N-Xg��5������Z�Eoq�>��\)����UF��G�FL��:����3����)�`�L_d��q���jc�O��!��6����`~+�_�]n��Jg+���d���(��~>M;�f8@�f���$J�QX�;u�S��������j�l����6`���v����������D��4+����dM����"�|u"U@�L���M||���f������@�~� �MG+Z4kt#>-�p�[5#���A�����1&]QE2���^)��������;�Y���D�����h��_��^�e���(c�[���Y�*��v.���g'�0�D${��ml��U)7�.�������mm�RS����5XB�m1�B���U�\zp�'��/��5���#W	��ur��P'��]���K����IA�@�mY@�������wf��T�e@���f��U4[�p���v�E;�+e,&Z�tL���X������Uvj��~�V*�2����mo�2U�Z���z�����EO}�����$U_�Y�w{V�)v}<�a�	�x������hW����#<B� ����E%
�$�l�;W�J��d��p�|�����$��������$��irR�X�>������J��q1>��z�5����jbl5V���
�W\F O�����A6���
6��hp�����9������q��l�W��������V�1�WZn�^���v=�b�
�����aX}B��86�T�
Az�����h�/�����h���K-�:�z����9��k��g��!c���Y��c��v��h��n�Y�O�#����aR��o<�6�^�Qo�0�Z��tl�^[�h��;wL��Hs���^&.m(���
`��i�w��#��b@u���}�]K�J%�/_�>��y~�)C6B���y��_@7b����Q�a*N�c�!T)-L2������8��
s<]�m�Jo�l��l����������S0`����`�R�0~r���Sq@���@�?�l�9������i_hK���F.	TJ���b1����}�^~�V�5���yi��g������;����*�2�v��^q�7��4>��_\��{j�8y��+|8�����cw�p<��^p��=���+p��q
��6����f'g['?�y+(����6�l<,�����k�O���Z��Go^�������b�^m
b��g8���r�4����5���7:(e���R�f'3�X�OG����r��-�)"R�����'�����la ���@���(x"�v����T�CCtNp��F�DzKF����P�*���d��@	�����s��(3�r��V����B��n��w����s&m���F���QyY���~���q+k��������g#7����M3)��GW��gS6K��3[H�d$VnV���c��eU-5��z���3���&l4�L��
$�^D��
fD�q.Z�i]�$����~��,E����,N�?Ou�K���VU�����$��;��N��M�N/Ea�w���^+Kz�I�t����\����'l/=]u���n--J-U�cieC����pM������e	��U�c�����%�6����P������G������z������vj�p���6	b��l�	�8�|��#iW�:��Lt��y���������{v�}���L
�*7�V��8&Z$����TTy���1��"V�D:�;�%>f�Zuo�����D;����\L��7_�������W\�kz�'9P(LBF������q�|\(-�P���s��U����f�����C���X>B���L>v�V���)Kk!+&�^�K� {q~=�U�����;���p�:OF�����s+AU��&lU}��Q)�0�M+��$�A���j~�y��Xm��E&�mG������-��M�:iM,PlP�������n��4;�����;����|O��5*N'�&��N\|�Z^*�G`p�m���C���:�D���z�J�j�)��IsF��#W!����9�����L���P$���t�������zk�QfNV��}Re���F�G��	rT+u�R�6M�'_A�G�L������� R�-�r�����0j	C��XN�''�J�K[a�SM��%)e�z=��]|�G��p����h�����F��-X{����x!�����(.�v������kT����F��CJ�H,'n
G���i�#,�8����;yW����|�;f8#�2��E���B���r��i8F�4��N��C����pk�;��%X�M6z=5��U#N7"'�?��)�\��0mT'Q�%Z��}��k}%A��F
��c@�����	
�QDj�$��P�5��?N�-#��{��vJ����S����.����(X�t��D8�R���j�_!9T�"F��q��w�����8�d$��T��r�e����Y��X�����2]�j S3����,���383������7�B�>�R�H��Yk�	R">/��w���	������Eo��5�!��#�(q���K��l��2B�+�V+��������3����voC����T�����aG�ZP��p��
=WK��!�dJ��4���>�]�=>�9����O'd�������
0-ES��<��_�{w��_��I��g�~\�Ake@�ZSs�z���j��/���M����)��bM��	�Gd�r����@@U��/r���6��)d>�2�A����E��g�S�=l�V�5>_�!�:u�y�������:D��aL�t���-�@g����d�)��K����W�5IH-����h<@�
 O�� �6�n���@�L\_,>�]s��Xg���Q10�[��6�u��m	�M�����|���py
�n��"�g�f[�\m�a�������W�����A>��J�p��je8XX��?T�eR�>��r��9�����7~���BXG���+��`��.����G;_:+fU �U���1����^Km���F�����l����kf+�d�1H�"�k0Fzh�+UL��_��x_8���18���(��-������u�!�?���V��V-�v�����������5|��������r��#��%��������2��r`���*&�J�!7/�-5�c[�3k��Z/�zs���D��6tJ�b��N�M�+����$�#$lI��s@��Z�=mTG�`�2&��Aly}�C��d���	����Kn��c���N������M������������7F�
z��s������9j(��d�������o��n�=^�z���s��_�P�����=��5a���&�T9%���]x�%s��p��y>�x��t�>p�J�st,�7���7���K��g��:��zgG8����f��V��;���
������!V� ��=��S����]&�O��mil��e3��xAKzLR��6�8������������Y��
�u����|�\����D������"��E�7����
�����Z�0_m��x6��]�T�8��X�����aX���d�C���Z�Sq�!<R%�E�g�4A�q��RR*����>#�#�i��R�)(��]��s�I�1�����1���"%�PX��m�����;Z�u�*��[�H����=��+�f���wxX8FT��P/����-��wBcId������@j!��zd��4Sq���N#*J���\I �����r2T�*�\6��U�V�Ut���p5���C�L����l���!<�?�����L�^9�=h�#�q��|Q:��06v�,�`P�%ZJg^F�Z)�b�I���n������[,�����}�	lu<�Z�P�+
(�s������2K��{{�l��f�f���\�J*��;-k}	?�ez�=3�V:���%F]����H����"��W�p��>Q���e��c��X��ck@�u-�%o=t�����AL��2I�9=���1��������S���gK�m+�k�&�/���5V1���X��0���rF�i
wH�U`&�V>3�4+���#��Z7�p��!���~9��\�cZ���g2&�sN�����y:�#�IL@(=kJ7�7�eP�[�~0PZe)�e��w;`�L�8u����nB|)k����@�P(vtk����3�m�^3�xKv���Kb�#�?A{��#�|���6=��-��r���Oh?y����5Z����7��fghSj�2`l���v3�_�}�Y��a�� B�h0��a!��rX
f���B��f�t�/��6�FG��x��-����X�}C�-��F5kC�������k�z�D�>K��J[�K�A����H����OzXb�{������
��o�^���\'4�4[��J���T�1[y(~t��p\�����.[��V��f���a�-B���"�s&��rz��
�2��k��p *��E��x�
�0���
����h1���@���T��D��=�u�z��I��1�c���D��&N�Xk��jU�Aw/l%z���bP�&*�Qv���TsR�}����m~�2����L�Sr��fv�2���Dd����41��6[*��9�����%{��`����nW���}�~���������
�U4	G���p;����eE���0��B�v�_�1�����b��"��NA�f� ��'>��,��S�����y�^���j����_�-��E%�������f��.�k�T<��8.~�������{�u��<.:JA�>��f*,�m�$~/��m���+S�N63��v�U�x����m!�E���,L�2sv��]g5������-|�:L�3�"�i?��sF��8	"�?�:�J�R���e�G�����C`b>���Fwo�-��,Nb,0�=��w7�ox3JPpt�i\�;'����{��������������S��9��+~pv1��w��`�;@T*+nQ�G/��#�#��������b}O|���?�G���O:z-�c�V��} k��������V�U�@��������V�w�������-�����+�����&���7�k�W�y�X>Y��it� P��;k,���f�p�����5���p��+}�\R�������_�Ydp�,�+o����ZIxe��b�e	��T�s��6ej�h�<���~�88���G2�2K%f�/7MO���nM��%�S1`�������'@u�nU/�(�L��s�1�'fm���tx<������f������wh>R��0I}���9J���,GZ?�V;y��H$�D���G�t�)K�o@���w��6���4��?\���0������-A�@Vcu;�lA(�|�_�M��p�W�u�����SP��l5v�}b��e�P>	g��0�o�0{��e8L��Pe_��/{BF�E�
��|n�%�2��am��T�����5Sv�z)��\��a�5��j5�k;&��w�+`w��G�u���1��>���&�h�v�>��������i��~�w�H��0�I���1��
.>��'�����38u�����������X�,]I&����F��
&k�^^m�u3gnK	��]�t���q������Z�������������~�)R!�Jy&��V3.@�P�e�q��p:4J����K�T9'���R�� ����T�F��=X�������"���L:��}��<X&�2��C��:�.uG*���2#����?���MH�m�Dj�����[��w����I��1�1��4^^hm���`����nL�&,�,a�(@�+n���	aa���8�v��64<�-Yh�&��c��u&��Q��:B������f�4�b
B1�7�cm��x��n��y�j4Zn��Jf��1���k������x}O�����[��w~"%W��|p_\8!\Z
G)0z�f��g/��n�adk��M�1#l�'����aE�����j�J�#������A�`�����������I�����^����8i�{1|:���J�����������a���;9.����m��Q��{.������S��;��LO����G�M	��Q�
����8��-�H6���k�����;&���!���^��5���oE�f�����Y�yt�Z���d��3A��<�
�9Y/����1epuX�Za�j�NE��C$��	?
/0�*v�F�������]tQ]��l�/:�,���^HL�	�����{'�	W j^��y{��Z�P)���	�M'F����	���(��=�W<���cT������d�%�|I�F�a|���ZeE �����$�������{X�O���1�9���^p�b.F&����#8� j�$mw����%��,���4
�-�dl]�$N����k�lY;M�MK���+�����0Y��uS��p�Um4�j[X6�%��G�A����<X���H�K=��0^3�
������a�w���=�x�=��_8�I��
��(��/`c���\������W�N�Y�cl��K4�A���8U�
�1�l7�4j.�#iF1R��O���v�
��k�&�A�!.B�2p]t�-i�����
h�u�-��"N(��Mz{(+�Kn[������V�(\��835g
���f������� O����!�����y��xt2t��J#'B�m��9����`%U��St�N{���K��V8��p5?�z��OZ�����
�
�k��C�@�����T[��i�f(�^�P������/���Q%L�F��+�7h�����9���gi���1������Ui	�������z��������������a���cl���?=��X=8�-Q�z���[�����\qe5	��h�v�
f��,/�l��M,�	L�{�UQK�"(y2�r�m�Z�7F[�'�Qwx,#L3�u���Z:T
�L\��F�����).�$/���I'�F����8�&���wD��'�R{�����L����]��}������?&�4?cNH��R�R�s��=�AN��=)s3>���������`z��X�������biZB}��2�]H@�_)H�c`�R�)NJ�
~�)2z�������<�&'7�����ShW��S_,��+�;T}a�/�+��p�4-�����A���/�b�������U�8����Z��F��ub�F�#�Ej-�M��@��J�Y������>>,�����Ss�H1�_j�'�2���Du�����4\W���I��C�'(/���f��w>i�����y��3�zR��?����[� ���=����7����7%%���H�{�?:�40��������`'��'�v���"���c��/�1K��|z7&�T�~|Swq�dW���o��1uX�1���~tL�]J�;����%#DG���&�`�;
�C�[.�g�j����C���Y@����`�G2,�6�G~�
�����n�+�tzH%�=����}�;�����=�_z@�.���������Y���D|F=�_�#2��������~��~���)$�!<>{H4�+�s4����G�T�������Z���#����v��������.z������9�?����t.�9=��?e����!�tz��������S�+���3��Ar.}u>�5
r��R�w��uu]�����{z�{����y��6����.oW�e�����y��5����Nj��j���:R�!��Y�C�W�8[_�F\�Q��$�pz�
���fMGg�^�f�h��7�2��a�T��V��z-�i|�������b���4������Jf,�T�����w�V��^^����ecy���~���3�ra	~So�\��_&��[Ps��?��X�	���\A�o���w�?Rp�?{{�m�������:{��#ij?�:<<h�^=��P�Ri��_�/��]��-+w��+#>��9	�Dx���w�	�9;��?����&s�K����E��������w��Og��Q*�����/H�/��@����Bj��EG����B��p��������l���/���l�0��,�U�E@�',6���S����t�/t�������G������Rt��|Dm�7����,BK�a3��z �b�����������F�n��G���=�#�aAR>�0������a���*�9�������;�D.�}����I����>W�T���y%�f�O�1gg2`�o��W���_�P�}�^��=��~�����}*���|���x8�����K��a]%��4������}�U�,I�N�1�3���wq�7��?�w��p&=a3����'����O?X����w�?=���

z�@�TO�zv�;���!k
_�?9�������I���������zi�v��^�m��w�/��c�T���c8[��^�����{>��62����O��{�K^q�"}^�>��|s����thHuy�
3z�4�gv���qvj�Y�+~�1_J���]����_����A���/�1�����k:y���?�%�n!�I��_"������$&����T���K��J|�qE�K��J|�qCi)�l_�n	�r�����O0�r���� �jJ�����a�bJ��s1��jWL
�+�_�7L�+�
�/��E���K��H|�qW�/�G��>���A�6�vb����xm���8�������W9�e�W�.��U���������Jw�wW���WU����qQ%>�^T�?�=e��@��J�H�-Ej������/���xe��r��s[{��5?���<c�F�������}dG����(^flS����+X{a�������.`�V>�Pmr���'�Hu�I2,�)F���a��N/R��jl�^�W�C��'��OR���a7a4�b&R�2x	j��J��Z��F��7����g���������V��xe���f����cJ��2x&.JI��B�cq�lo��=,�Z<M���\{���4)���2�T<M�=t��������1aW�O���t��|9��7#Y@8��f��BX>6���6�B�u������;�	�hPo)S�}�g�����;���Q�LSJ���1���x���Ih����e��~��Hx1�����V&�d`�zX	4������0S��$<K�������I� d4R�FSd����"{�x�$����f6�-�p�����:��������e�s�z����2b����r�����1-�p�����
��n�L��pZh�\����"�J
�����^���u$��9G�y5;����4��5������:��ub	��k&��H�Yn�MpL����z{Q��$Y&5G_������M�?�V���)�Xl����J�������(��'�����{�{����*�D�J�����o'��SU���/�;$���%�d/(�)W�#������:�H�5�KAQ�u��P�[c^������-����!��:���NF����p1�?�����r�}��F������QgOYi���j�S����SqIy�����A���'B���"�����s��3j�6J��)�E��%f^��9��\���|%fi��33�C�:+2an�PHO��>���7����gD��C�A�fg��
�����b��y?�����[�����8c������M=%
�/,y���
"p��V��d>�]��?�*Q�#��y���Z:u��j�3h&*��Lp�� �����*$I/1J�@�I���Fy�2<��:A�l�%e���\��w�R�8sSQa����:�u��2�!��=\�:��K�����n��(�����n��������d�t���yW:���YE:�|3Jq��W4��	��-Ku�aAD��\��ix|�7�����2��'�`��m�7���;��3�3u�f+�1��2�(���L�=~'+���o��V�B4�����_������s �x&��,���{'�fkO�s�h���������*8�|�C� |
3��"J��������O=�<OCiwW����M�Q�������l�Y��*��������cc�qz���6�Ss��cm�5��Zv���]���QN�|9�:�et�\-�������N	����a���IL\�4�ms��������)��R���Q,����mx��=��[+ky��g�R�E��S����x/�����W��B����~�}E9�0sk�5�"m�U�^�C�z5�����#o�;���������k8�xK�{(�d�f������S:`�7��n��Oey�pU��q�T��\����k��< �
���[i�ddX�J�P��p6�B%��|�B:m7�J�����8'�����o��rd���R�df�I��FF�����a���r��f�7���<JlUl���:#%������j�6�oJ���-��[k*gq]���7������JZ�9%�S��r������98�$�Gr�7~��,�yi��[#�4�FUz  <7��Da<�9Y�T�d�E8�/������*����O��v1���v���0-��6h��k)����(��C��D�����:�j��ui���d�O`�^"��6���������Y�hX��~;L�����p�~��6�U�D�Zq�����
V�i�)�Y�^.�����5X���	�6�x����IT�}���,��_$ 2���cE�V�m�����
`���e����� .��%)�
�e�g���t+��Y��������#��i�R�q��By�c��oF�����hP����n���bm:���U�L��.����{������uoM�mz�K�-A�b'F��KZ��	a�D�W���}���imIJa*��P����!������*�&�E�x�-KQ9�$�P0��4R�%��{��������T~:��C�1��py��N�M�k��Oa`�:f�f��o������4	�Q��:,���������n��y�5�L�=�.��0�y'�qR��c�5�����S��,�t��Bu7X,Qc=��������<�G���u�w~>8wA���y�g�?0��:Ohbd�����d_�v�mW5����N�^��\h"��M��v�i�^�w�E��=��_��}����)�J����)>KK��X,���])'�06^��s kkP4�p�R�k�*������
�RR�M�SY�=�������hy?U���ZC@V�\������tDm�xT,�y�?9x�F����[���	o8U�b�E��	9�c�I�?hW��� [M�8 ��[��jB2�d��`��i6bo<#e�Uqv3-�����%k��H�[���r.D�lV�^v����b7$��@��|�r�o��	���yLR��4�� o4��#�M�i��FSzj�����Pd��'�V���p�����1��yK:�D�Y}�'q�r�9P������5;c�U��~�����k��o!a=��_a���rJyKWj:m�%����
*@����������r���;[��;������@%�6`O��)����cH�����@����l�Z,��RD��sv�6hv�;�Y�D�����'�S���[���HC�c��Ep}�4d�=�Q��s0]���$���W���M����V��FS�UO���i��N�l���a�nz������U�Emg���������b(�]2yC���}w��W�aB�����U8Yze�&V������g]�F�U)Wp�����R����F�t�:	yH>v4*��=�R�3���YN�O?#ft�=�E;��_���as��SVV)���N�?]M���;���/�K�rzO>�3wx������]���{l3��������s�^�C�#Z�p��.�`
�A�K�R]��j]:�i�Ez��y�mt���`m�\s+�J3Aw�4�0�����+Pa�xK-�,Icu���7�Yy�@�A.�f�����8���1Z[�P<EpO@
����w��7���	���Q���J��Son�������L����	���N��R:��M�����f��	V��z����A��}v�o���]��1}v��
����b(�hC�
}�������,��<<THDE��Tw���Ew���V]��6 �+��cg��(\��"l��(�tj ���k
�R���VE�8�s)~��u�B�p3�w��AJ����(s�fK���U�^R6�e@P_��D0�~F��\��9��tS��j�S�G&
H$��p�o5��k�J6�t�M���5`4;��c��1X�:'NS��PF>`N���\@�*XpR��'s�n�J�=�#W!Vad-����S��E�j�`�4���Z�J{5�+3��8��|�|����)��`?w�O��"r��f������/��������C������%�5c*��w�-�J�!�w��,}k4>
�ti0w�-7��S�H@/�;`�B\�,�]��y+,�u'o������IxMd4U�����9���~��F���
�Z:�O���7��%N(��&��2�qx�5�0���R�+"0�Kh�?v���E�::��c$K�P%/��z�Q<��%t��'!�(����
c�kN ����;\~F�tFB]���s@G�P������bqP���9b.�w�Z�{���hF}^����h�L�D�������,���V�) En<��e�C�����G�c��tVU���Hf%u�?��� ���?�.��h�?.�G��?���!�<J�)���VSd��o�7W�����X��������0fAX���h0���A/P�]`��������-�#���e8"��GB����n;�xp=�:��}�Hbb������7�9'2y����p�u=q�9���JE�y�9((���P@!���!��EN�sq��k��pTR�Y1���N"�wGY�P�E#j�4i�5n6��r"*������"�Lw�c�����1rb�!�E������Fb�q>�4_=�����AP��R�h�^+�:F����=�G� ��c�
{�A&C�W{{��1�T����+�$���;�����7�X�����}'�Cp�������p�(��B�5�������v:n��H�b+$�Da��h�������u�I�����*����@��D?Zv�=u�o-���+\Y��;q��@��iis���+�=�lS}%��<�*���#�0���?��Edg
�.)�V�0v�����}����71/��3����],��o�H����@O#R���O��{�
��&C��(�c.�m�WK�p���q�,s�ku��r�_�"w��<a����5�����P��[o��t�g'�GU�[�kq�r��s������b�4X��N2�
�8o)-�?RyU�[��3�xM��T��
�y:�����9=,�^��&�>�P�`����=�Q�U�\M�y�-���A!8A�$jNy�$*I��#������@�/�D��L�7��u���o�����/�������?�K�
Q�<��9����\�����EU�GvD�Y��y�#W;q<LO����jQ��K�]
������h���S��pf����UPi��Rc@�2�d�G�R���``��W��r����l��$:[.�������s&B3��=�����O�;[�!��M��z����tc�El�t�z}\��?� �F�%�f\6a!�>
�_g�GHf�������s���<h
�)�cy9
fW���qT���������#��5��A�2����2�~����<c�+��*�����{{�F�Q�	1���	�7F��[6W��r��vN�ki�E����%/��L{���,n$|G�ZZ�)\�>��Z�n��7�WY4�����N����L� x�lPI��7}�C�kL���)X�J�
�)�c�GJ����q_�Q����u�3x�_y����IO����1����I �%I@�`X�L�,��)�C1���O��l�Aw��R�)��c���<#�Q�mT;eE�)���8��S��0qb�*f��5�Z)�L���FZ���C9��SR�`��KT�p%��������P2U�8�q�(A�2h�N����WN@t��O�_�����`���o�v��M�i�����I-|��20J���-�M��62~�'�3�C�\��pR��(��_� ,GZ����g��V�DC��`��4���
*��D��0\-����DZ�j�+�:���5=Y�?1�A��S���ZnM�f�v�d��������3>T����?�z3	$G���@i6�J	�_�r^����a��8�_'������G�������S|=��9����b��'m�"?���3gp������tp~�;w���a��%L~��4&NC�����}JyZ�����#^(�s���7]|:;��~T[H��:�?�H��\�M%���X�)d"q p����x��@
�McO����|�`�Kd�18g_��F�fz�'�V���r��9,-���R�/kc�Ro�=���,$Z[����#�?`�?@����	P������%����tuH��$��p���Cm[�e���d��<����=Y�����~�.�Q�\�I��D��p��
�A
X���C���u���f�4F��m�]^�U�Bb��^�hs`���?����0�����=��C�O�U��`�~��=������+��t���3n�xb���>�<��Q�@�.�����V��/���o��	W�[m4�V�YO8��I4��tn�;-%��8V�?�`��,:MSm�`���_��D����D������*������6�1�7�X���j5��]�����z��������(��v2��6Sf����%���B�uvl��de��9��I}7\�O�n�j������$�@O�. ���8���J���L���������s������Lm�/���y����p���P!�FS�����u�S���(#��u��:���S��,Gh������F09>q1�������$���X�X��o���o���>��kL5��?��>����z���-+:����X/�^6t�����0�VA�����^�%���e��S{�[��['�8��k�U�=;Q,p_Eb����M�@7\�P&����xg���7'_�3k'���9�	�2���'������� v����J�2���|8!V��p&+���K���"9qh0����l0�@����/����3������bU2���Y�G����^�/��{Sn�Q��TS
�^�G�;���o���o2"��n�*"���v;>j�b{t�{��tr1������'�����V��*�� 	��4a�#`V�Q�&FC�3��\2�@1������(�5���~�Ul�mT�Z3���
����o:3(*�^cu,�����JX���o��s`�?�2�����|�)�~Kp��L�O0�A���+��w�^������;�|�;>����'���j����v�g�^�	��eH�>����x�����h�
������c��A!�4&8j�.��6ZJ>���C��fO��kM�����z����+?��g�n�y�'�������\�&(T��%��b������Z���>�,�gF��>��~%����(
�uV9����7i�'/n�i8����l�� ���o�w�J��S��MR$�;f$F�M��~EtJ�|�o���{gx��b����r���+m�����igZ��1���7��Y��j%s��Z��kEv�]
(^m���*'j�B;�q�c-cU�s/�K?�J�������ru���@m��W�+i�jF�;������ X:���`?&A��L�J
V�(��T��zm��H�o�t�Tc.Y��Ur��+5�7�I��J'T
�������W����X����i�
�y��>}+��&��K+������?��F�
Fv���y=8�)Tc�,�����3���)�:�G��D7~-���~�)-v��S�bEi�G��MM���e�t��C����G[���o'��M8��z���_���P�B��en���F��k�Y	��c�1Vd���O��������O3z�m�l9DrK��H{kw����j�!8����gIM�|���/���7�����Z9�'<�:Y����b�Q��P�/�8���~���M�Ly!��e�$�#��`�tn���������9�Mm������
�G-��ngr�?c�����m,u��+�����&_k�e��5/r���������Z�6�����o���O�O5�
�����"-;�*t_����{��U�k��e{Q���7�n=k�Y�DO�}9���y�9������q["�3C)=���i--;G���t��u�O�j�Nz�Bz�d����Y�K��d�|}�rt�
`q�4m��S���>��}����uIu�h,�����ZN3�[�h�#�������[��N�.>�����H���@.���~2�
���n���#A�:Ks��G������!`>���
���r�&�Qi�*��W)r(�(�+rs�{AU�V��� H�0��� ;��B��������hM���5�
S�K������P�����������0���������f�mU�
�k�K��V7�[�����������H�W�&�G��;15�F����vd����"]�����:��%���3��V��>���O�[����� T,����p-��b����Vg���p�����e��o@��{�5 ��]&]�K�����tfS.J��W��9�{B�9�^�my�7�A�x2�z��������e3��$;��125�nlN��S��})�^��Q������`b0���{��-��eD��w���=�?�ab���o�3����6�� 8���9��n�QI9�h��H^�-��6����p8�4���>v��0�)Z�����[��0~�59�9j�N\��1�����?_�N�h�Pm}�xn�e����j�
���:��T}�4�p���@CQ{�7}�	���,�\��v��B�$`�!�����.P���Z�S�d�*���|���v��������N�:lS���1�/F����$+u:p����{���_D���������2�Y���p����,�H�q �Y����M�K}��&!��#J\��������s,9���N&�+|�!/��a��1��u�������JF�����sl����`�jF��zG?jZ�!6�k���&���X�xKSK�?���"���&���
Y�t�7}���n�P(������q@��������ps��T����g�i+7Zx���}:���S��]�+B�����4b�#��T[����l��Y�rD� PW:�uC�j�V��:�W����>
�3���3�;�_Y�o��,�Q�7[r�e�OE�b�31�7j>1/������M(c&���&�^?�o�|v�����I�*���fV����F�0����L���p]0���_���jdB���.�O8���T�p��4�����`�&�C�U��O0�l=(a$�$��5W��)��g$��9�d�)��J�������g��;W�q���c���X�E���.BU���0F/�I|��W3�;t��+$���J\P(_���PEW|��C�:���k���nz����7`��q@����d���c�u[�Z�2�-jP����4FrB"x3.�$J|�	��R�w$O���@v����Y���u�����|���h�M�v����p~O�E���U&�o(�-��������0
/��cL������W�u]�]�N�q|��O���{|r�Yr��,���e��	Gnz:��
%0�{q�������`D���Q9I�%�V��#�������ExK���C� �/��q�(����"���
D��No���1�*V�:���y���y�7��T�
�'�o��jh<}��d�4ugK9V��M����d��D�+&Oz��A4��@4+/dSTi~���)
�`�~�h[������)a[�!f#{St���L�D���_o9"�J�+&fr,8�V�����"6�`b�y���������T,���
z�5��Q�.���3<R��9�����o%b$��	�\fW�T�A�l�E8_�g�vaX�H����X	���m���[�e|I����tg���\
+k
l����m�
}��6D�B����/yAl�!�\TYf������d���7�3�O��?��x@	q7�%<���� �C�B���.����tn��3�>��n�T��������j���������p`��Rf!���Am�����=�L	6)�Q��.+�����3]��#�������v���'DZ#��(q,�@>L��P.������mHT1�u���$LK�ELGW[%�:��f���D�Ml��r`kw�t%�?M��w��QUv������7[�_�Uch�Ex��|�I��?���4���y�����^��4S1w���_�J����9y�� �b�M0H���HX������w�5b��mH�I
E-�u�HkgW���v,���N2U:LNM�&�Q���a�������"�6�J�VN���Z��$P4Q����\���G����?#�)\O������^t���14��kU������(~ZX�6g�����0!E�'E��6e�	L�����S���N�6+}8���>�;��,��s��h������x�����8N��)h�V����C�8*�l�w`p��^�?��@j(���F�������T�����:?�ji�8%����Zk�P:+���5�	}�8����0c��at�)(M;��?���p�%hF?tO�O���Y���rd�������7x?:�OQ��.J~��Q�����?�j�[���[�3��mk��e�-���x������Us[����A�sPy,�/?R9�O�|�L����jn�'X�V(7s2�5������w!��L� ����a�[T(��!Y#���������v���c//c���;Y��4H4�����$$�l{
(��q�'�������s�/�t��o�<C�~��@��V(O�-G�����t/�;���}����]PX�����N�/���_��
����H�
��?��gBf�����)���Dj���$&9}*?K���<T���e%m<���������8��;�2���A�s��g�����i���&��N��|&��lK��ukwY�>�x���p�y�i���+2��	��G�����������6T|�,|	Ppe��	
T���O�=�L�d�vY��?��m0�b�g�/>M�����h$&D�b���\bR�����sNG?~���-lHjTLc.#���I��\a��v����l���_���^�h���v���k�k+���}���������$t����u������j�Q�F�
k��*�E�Dg���-b���^�
YZM�%�,��|�a�9�yWJ�x@��E���b_�E����KT�B���BA���w�����d�����
�v����C3&=�{���PVa�3P;���2j��	�p��������k,e���ZU��*���4J�L�p��A�%���������[V����l�������V��r���_����9w�>�J{2�4�+��$�)�+�;\�	KU�z���@�X�Gt �i�d��
��b�t������N,-���������]��l���;��B����m���7O8������4��#_AG"����O[@O�:@
��@��H;y]�)y-Z;_���Y��8B�A�T���!����TP@����2���>��pw����A$}.�mD�#�DY���4G"�UZKWcJ���!\�?���$�8Rk���n��kY��A8�����"{�@�O2@�k���^_����i7��P
�5hd��zz%gL��*�,�Z]kC��\�Z����T���
qt ��h�,dz�"x�B/1��y����������e6Q`Z	�o,�1�;����M��J����?�&](��l���N��V'>z9U��V�=��.R��+)�{"�	`�����-��?���C'�#to���
i!���5�DS����V[I�eb��
MuE�M�D"����c����h����K����vN,_g�W������B2� ��G/(����c-�f����Xq��&�zOJ������>��X��P�%6W����q+��^�!X��f|f�s3l���B�E�`�YH2���6Q���k��s���#/B`m��mP�5Hn*���.%�3_��L�V�������m�������yq�)?��r:L�dL�(�<��w>L�������l�&��(Bl�g1$���m���� V��\�?�)����(��6:�d��NG�K/�G�E8-�1�TH=��p�������OC(2�;S�yS&�Yb����M����7��Q>'�5���&��CYJ>0�@�nid����1�HT�m`�wj�������6�:q����>���hG<2��x������������c�����sov�������!��l�#kM�?�
��?��*���1f�Z`
s���y��r&Yq����E�����b�D<�CQi��P�X
�1��y�w�f����$<�r��z�5"gwj���T�~
�W��R�����?��vi�A�����d�,���E�����	�*jQ�=��x����x}a�#�z�.������[p2��h���*p�\��_P<V���"{K���.�HFo�yCS�]Pq��(�r�X��{�����/ml+���m��	���$���]_�~\�Z��h0Ly*��j������IA��a�������*�K,���Ol�c������i�?����JL������13�N�N��ti��X+�W����V!�5T�s,v�Z�L����<GjOu�9?S��wX%����l�J�a?*��-������"{}��i��*��E��O�>����e0�z�H�_)!��t;����������b��l��]q�x��k/��[��nCS��u����/�/�-~6��^�����������}\��nuG���,w}o[�Uu�J��i�!�^�3H�C��{�6��k_\���O���9��T���+��������6Y�J���n�I1�Lv���e��8������y1�?�W;�r[�R)�$��R`����w�$%���w� �u��N�yQr7��D���<��/��������f���15�w�?��P���/�wFg�2��A]F�����4�3��/��cJ|���b���C���~4�TEnZ�@#��Eo�[[rg	�cNX�-��_���Qr�q/j���r�g�6�$���j��#����7����|�����o��;����&���|�� �x8`R=)�,�E�C!�Q������HO��%,m}lu:��b���:�|�c��?%F�m����Q��]���0���Dg��
D2���?|,��	����/}t�"����\�:�_���K������K/���=?�34�����W��&�����F�TGj�
�RK��t���9]�M���La>L]������2�!�u�O���\s+q��S�N+��������q���*�k��CZ4�Z�j=�4�Jp��<���[����'G7 e���	�bka4z���F��H���l��E�M�h+1xDz�x#��@\��[����!Vo����������	vm+�o�b��7W �o�j��8����s��O�w#��L���1z�m�&T�X#r�|���	�,�5��N��UV��\���|g(�����Q�J�/�f���-�~�#V��J�>����i�KI��4���������%q��r��_V���Dr���aF��S��������9�E>�`fQ�n�*S�y��K[P�3����/���op��j=5��4����hs�>b�E~�����da{���,q/3��&,3������s�/�QY,3����?vEc�(T�����s�'T�!sLI��W0�Y��V���5���f�<?K���d�(zqk�N<�!�q��x Q�NB��b_9��������5S0��ih�^�O�&0,~�v��CB9s���YV~'��Y�~��gpb�����j������6��YK#�J����"q��N���u'eoQ	/����b�v��Kq=k���Q�B�/�P�V����KX".������t��Dd���^4\]����5�d�O��zz/EaZa���� Q��3r�D�&��}�����"�8N�'F��{�l��	��O�_�L�{;�`�s�������VQ�C��8+�{m�Y��(�j��]�7�����e��[�4���}.:���>�2S	�������E
,�	�S�� ��@���:C���n�J��������zZ0��k7$����NSl���T�T!�l���$b���Y�
��G��L�o$_e)C�!��X�5aF^1CJ�����[i���NK/ZE�@0�<U(����2���rRQ�e�R)%��5�F������v�;���{����b`�6���a�GL5�
�8�$�����<%}���n������`E|@��
��/�y0�/���A�������x	�1HsiS��|\S7U��G�/y�Z���Ks�8���_�{wv��;8
�������p�o�>�N&�-o���E^?y@58{��YQ��f��b``tV?F}Z�["�;��������dz"v���'O Ja��XNc����b�+ax�Gr�l,2�[K �=�k�%zV�RT�n����j��7�'dN?@n�;M��.�f|��~���Z|�o��`,���"5��p1�Q~'��!���	�VH��*$]�(T::):O�n�d�g�F6q����w��y����R���i���M����*�F}���L]@��(��Q��L_����/ES�a_k��+�o�t�yn������6-��-2���j{kw�j�n����;����UC���Q�%<.�NgA/R��\,Is1�3Gi�9���>�`5?�9P+e�Vi�YI�R�V-m% |���$���1*S�X���gZ��p�'��x����k���Z��nM��jjk�G���������+��I[]�Hk��I<����������S�-|`�t�	;�Q+�I[CL�u��X�zZ��0����������H�F�' ;>��H��;���������|J��_a��7V06���u`lV�UG��P��VrV�_�>x�2S�y�f�p�{���=�k���y?8w�����sq��9�����)�R������^i��@�Zv���p��X����3�O�]H`m�E�����af���T�����}��+�}�te�Jz3'��E�J�
^��t�K�������gW��'?J���?�Ix������Q9J�-��^_�,G����������'�8�`rIox���P����hd���[n�R�Z67fc�r�������#@��{�=Wxqq���<��a��#�[�/���\�oBE��Xy7��"*��������;� ,��UR}������������y�z�h��U�g����]��a�$`^��V�4kq�{�U�B�S~uo�?rD�Air�Kx�UI����
���jT!U5�(�����|��`��{���0�m�������-\E>�s��-d����auUw������o������
����Q��]��!���a��xv_y�C�Yx����7e��$�T����#����K�[W`?���_/�}2������WZ�P�������@�8_;�����
��h�>L�2�����-x��3�s��?�wO���������/G?8�f
�8v2K�s����l�46��FQ��-n���{��<8?.��Co�Gc��A��7<��_'�����lv@cb��7��jT�R5���7����;�{�}{�>BRX�3���
�Y�o��/�T��������n��z@���_
�~���#�qb��-���/+����r����������q�}��g���ov��e����� �Z�.�������+P ��v^T�@���vu�J"�R�#F�,Z��$�i�7��<�"G�X���`�I��]�e@��6�p:95&��	��n���x��i�7s���������|�g�RSM���\����Y����S�g�p���[������f�}Z������R�Q���P%�������t.n�����������B�J;16CXR�o�zr@��u��k������I�������4#�g�{���Vl���n�Z-�������r+Z~����t��������E�{�����D�(�OS���������Y�FK�<
�enA������@Bz{7��^����h/a���_���d�����#�H����F��%m3>����A�>�w����XM+���5�\!���_��=�+|�D���X%�5=�.�t�a��~�����'c:��.KK0�Up�=-�x*z8v��`i	���A�
�h2RB��as=v��<MDh�'�� 8��!�W��Y)'�z�>{��P�-�FmV^_��?�>�B�P~R��T���m��w�1�q�����q������:�aP��t��Z������>U�`���4<o4!k�:&�8u�Z�3r	&��T>�-�.��:����+M�[�n$&cdF�'������B����D�XvJ���^����n�]ur�����;�2�p
l)�����(+����r�W�8�v%@�
n|X��R�d������;q�a�}��p����Hu������1�����z��f
�:m[�g���wo��q�;x{�Dm��a�
	NY����18���'�z�����2u���h�,��T"���������x^�����G���2e���~��f{)�M#��������y��0���cI���3~q�*vK8@��X>��������W/��D8�;Z�����&h�-]����I#��K_��H�[������l��`����������\��"�J�%��~����
����>�`�#�@���IM����G��6�H�<]��
��C���O�//������)C�3��[��v)�;�:���I�x���Z�����!�LF����F0���-j���x�gL5�n�5}g��K_��9�m����^��y�M����r�zrx��fJ�2�l�q��R��9�p���p!\Ra�8��.��;1p�����jB'd�x��D�_y
�G�C��.�y���~PD|�[s�)���'���������d�H�P����TC���*>T��������F~$��[7��O����pg0 a�T]���K��4�5�
�'�40�zC;����5P��m�y��9��Y��V��T��iW�T�8�����=��'�\y=�3�9W�D�������$��fP}���j����-�/�����N�'��i7?$H��o+�6�~�������_tH�U@����daU���������m�]��Fc{]���Rg[au1����j�
E7c��|�����<�>#�������:�6�O4��:�5vF�`2��o����\sg��S��W�0�
����v;�<��27���vE��h�3�TZ���v{��no�������`<��b��c�����L*��lN����U�.��.����hW�b�Z�m	�DI�(@�J�����T]�����*�����"U��T>��AW����9����S_�y��?&���!$"B�s>	�����J�'�� �i���GG��d�������p2F���F��u�����Bz��S��S�@��*?i�4���{����HH���#>W�NG�i��u>���C��}��!Z��A��O"4�����G��{#nb�#�����
G<uF%��_�G�	/oH��G��?K�Zq����oFd����7T�����)�D,����8��68�S,�buA��u����uQ3;�
j:��D�2�	��}~������Tt�QS�k�5��*�]��Q����uy�����k��{	U�Q'M�W�7�Ig���@����
��T'����V+�Hp"��K���I���Q�K)��z9Z��Ljh�>��$���8�@7��C�f
[�F)]5��4��n�� ���3�f���>�,���4�e���G�hV�I
��pr����~���M"��s��8
�O?���>�c�K�Z^�0��i�|�bSL�m���u��z��$LL���#��T�f��~#1���AP+��J�7�Q�f���H��c�����N���O�5���K��(����y�����E���p|9�7�+��r�������������sx���n��uGh~;P�@U_ ���������WVeQ�1K,�,U[��0��p����������J����`��<�p��q��Z��:
\J.�2�BLw�w��&g����������q���w��hF�/9�E�b�a>r kF�Sy!mxC���E�j?XjX�6�~��'��4���Y����^�]�7����z�^F�-��8��c��5��Z���\��
<��5n��>O��i���v��~5	H{��K�n����x����(��=6[������4����X�V��x7R�S����i�f5)��d���^������7m&��`����N�!P�O��H�d��'?�R��Q�
�0�D���[���
����f�r���+�L���x2��y�����2)`���"7$t�/9�d7��us�n��W���;o@���d��N=�T�	0�� �
�
K����x���s�)�F��X����4?�hx���6����/���)S5��|��*0��Mtf�]j���O���!�rq���X!q�����v�d^�C!!��e]����{�}������O���r��e .���{x_X�Sb�X��
J�iw����A+���r�jU+��a����1����� ]������h�LX��3��L�)
��q�F���{2:����v�;����.�-H_:��QF����s����(�t��6c\<9���k�@��hmK���c���Xo���ZoW�x��zJ%����jP������I3G��Cl���I*.A�3�*E�S�K�����Q	���x���J4����1��R?���Z����"o2H�&g�<SH�������kg��%�2�[S��Gdr���z�$�)�R���%�^�A�E6*�
��Qk�^|�*P�����%�H��X�E+y�?�4��)����~�~�5�>���o>����p�����W��cO��������Z���]Ix����&][P�mj�KJe�J����������LX���x��!}0#�
�2�k����������#�4|��`N[u!�P;�J��&2�N���D�����m�$�lN�T3R?@A���Ch�
�)�6�rc��0�k��qU�k@O]Sf�X��PX��7�+ �iG�f@PQ���l|������NcK��S
��������F���d�����H���]�H����]#�o���X���5��� 3/}9�U�����zY`�T�CS���d�*�HQ�z����/����h5v6v�q!rLi�'y���r���������f�&io�%\�z�������Y~9��R����N.T����H3'��$y����"��iq1�8�k�v
oi�?c-p�\���c�Gw�-���?�6�_���7���hz!�?iGg*����@=N�gt�Gh�CF�l<)s\�R��1!�	����y�^yxP,�}���1>�l.���*'��&Y�a�Hb���@����\�����8��x��l��,z���a66L�>���?�>�-����D�TH�]s3���
���WY����,4�s	��'�C����;��.�U�������.Of���g������������LY���I`OX	;t�cB���;�W��s?��)e�Dn�"<��!'�`����Ak�`�c
����x#���j�����lM$��S�����+�a@�rMdZ�H��HN���Q���R���0]'�_�|7U�����@n����A�]5��g���d~%mE�}�o)�a(c
ZO�5R�������OG�y�)@�����I��bHd�\�����
V!�\�*�r������j�g1b���B}7�S��[�(�WX��|����&+�1��,L�,�o�Q���X�e�@���IM/<�J�-�K���� �Y�(`���F��N�>�at�������1��am�
A��m��p#���m_E�0%�#���t�E�`��Y��a�GJH^k�� �N2�Qm�_�\]�+��g1�vN������{x|�� :���u��
<������,W�����W��d�C��!#�q8/
{5AF�g�:$9>9?��Xu��>e��b���9����g4�|�
�
����^kg44�����n����|�n%'�� �.���x�%W/}��
��w�	_���g�G��n�*�8�<��'cS$[�'��
�L�	�����wi�^�O,	������~WuW������ks��L!Y��
O��/V�(�&������&���[�8�x�@���c�+w)��B(M�9�-���0M�$]C?���[<��!��.��saK���a��if�m��A��d�3��	�hq�p[�T�|����������+�0�\^
i�[b��'0kV	�%��U���>
�Kr�����]�rj���Y)�������{���r}�j���:/�/���&�h������{"��dg8�v����ub��@�Md����[�������^�������8B��e�����%��E{�Q��|��x�G��9�����5������+�����.�7���B�L���i4�n�#i��E�Ns��s<\<~��������z]�NBi��������J�{���)&�aLo��Y��!����}�5-�M�3�Y����WK����s��v���gG`�wBq�����|3)��+U1������@�������������|,X�x#v_�h�i��H=�Ar>� �����FJb�XP��xb���h���G�p�����F.����H|E����\���rR���������hO3�O��K�-���*�n-�D���Z����X�r�j������V�n���3UMC��3O���qI�S?��~W��_�|o���Ol:0	�%���)����!��V_Z�Y�J�������y�TAn��4�������+[<��bV��hn6n%���.L#/|8	|J�4�p6$��<0Z]��7��CnAO�����R#���R��)���������MA'2�����H6��������$���~�_8�z�Kf��C]���R�"�J|�7����isW>�����I�Z����R�:3�J���@?N}K�m�#Y�T]��F��Z��>5�#H���.�C��f��.Y`�������X�N�9haTK"�cb��o��`6)l���t�c|�v���O�S�V�T���J�T�9U�i�W��.\��6_���^�����m�%��������B��k�;���x�|>s���������v�ON%��O,*L!7]'��\"Fv��'�]C�\��u��K��w>�h���9NV�l��+M�E�8�W�v9��h}���_
��I�N)���������n9�_�V�������^�\Y��G�.������,C�-[v��9���o������kf�b��"�����Y���Jrl�^��c��:i�l9������b��jSn.hW�(Ff>:��u��.��/�����rt���)C�)��U��Z����X�g_���x���]4t��xe���j(0}$�>�s���o7.[�n������=�mjL��������qA�.'�m�����(cro��}�);��:�a�/|L�����W��"���o�b�%���N�H��Rc� 8���6e����.���Jk�{�Z��].��)�P�#e���T��DN88l���.�I��U��)K??z H���B�|�D��v�m{��E�x?4��Cj��~�-�yU���zg���$)���.&Wj)��x*B^�k�#��rC,��u���������@��.P\)_0���I�Yl����E���e��J�o�:��7��:��Xh���,�k����������_�.���T�
��	Y�d;8y�9<�h{��d������2�R�QV���aN,gW�A26HXo5�-���*���i�]8$t�d{0����i	�e�!��m�����<Z���?P9]�s�=��5][�$�Q�Js,l���\���YX9��}�aBM�1�n����A#?��
>��]�Y���}�[<��E��Z������!�N��������������������
T����U�i�=��������N�}?	�b�-�V�S{P�R/	l`����4��6��i}h6R8���Lo%�*�W4��N:�D�\�D���8d���z�2�ab/�{�d}cs�k��L���>*����{R�O���-h-�AK�CJ��|��a{yd������U�P�%������9����f�����,��N�W�q�~�;y���IG:l��!�x��JS�=y1������nM�(m3��9;3^�j�,^]�Q�/3��H�I�{���O����sq��������7�O;���Q
�9�Sx��ME��2����A���g8�|kr{b�]
��z}���O~0��f :��T��L��6��a��3W���,P)��I����@�=����r�����T��Qg�daC9����P�4���3�]g0�F��T���w������<�UjH��2G�BQP��	�0�!�au{�3&����eq��$<��}w��])E�9!������������..9K�)r������My�[������]�v�IPJ�`NyR
N�Kyc��&@�I�G��AiX��>P�����(>��F���:�O��S*)6_�������<��Y��==LDt�����R���������;�����~�h<��2�%#��mQ�W��A�����
M+�Y���<��#�w,b���������H�fK��5'QX�P��0U8~��\�,��s����W;������W(jKr\���d���L3y���������f�:��4 h��3ZO^-��;��(%���$�H�,��
7���Vinn����-R.��LA��Y���E����e�5����3{����+j�|nsV�$��%J��-�k��m����,��M�%�h^���i]| _[Ntd������S��l��	m�.���<����v�������j���}�p�g8vZ��Tp<;�v3A�[g9*%3���D�[
P���1�����a3��B���c3��(E������?.��0�����&C������d�����
w=�#Z�'�+++��L����������v�G��sX��x�\;!�����;��� Fyw&��7���"���H��l�L��~��7E����>����d��%3;�D���F��>�Hx$�������b�����A�n�a�����7��c����|���a���40.���#<�lh�J���������D������E�89<Ex�O��}��7�^��x��22�_
�YS������.��%��Fss������:>n�)�7O�.����l����x#Q[�@���r�2AUW$�P��b{u��������-���O���������@Sot����t��,�N��57�l�����q������9|L��������C���A��D���2���5.�a���Z��;?���������h�J�qv�F�o'�����o������-�$~��?��^@��{����H� �f{g��C�P7�P��V��#��L/~u@�N8w<Tun�����'���2��~��c�-y��
7��[`U�&+t^�����z%�,@3������_��^$�wV[�3}	<��1h!�J�4��"�K�#-�UX�Y����6$hk������eB���e������+�,l�,�u��h7!�����3�cl�jb�:r�&?��D9�,�i�����o(�%�M���h������r��bQ����23@[~�
Vs��� .*�g��Xi���~�h���:Fj��~l����M�����5�6�D+i&U�dZS�i���P�~r�T�K�����SN�����V����Y�u_��	�R���rt}��[�0NS!�Ab�B1U�B�������fo�}tp@�gP������%��kZ���m*��yc�o�v6[�,k�O��E����g*K����k��������U��������^U����X��z�wF���20����L��H��O����n}Dn�t �y�:�Fg�����g 7��kwD_"��>�t�99n��^����� �U���H�&�P����4;(=�(�%!k6�E����^�nl���gSC"�\I���f�@����iB��7�K2!�W��KX:�,Y�����0W�CN���@�8h��W�E�&�g.U��
�a�ZA����D��8�cct��qb8��t2�v��t�#9����K��h�5���I���oP3g��5i������-�)�o)6�[�)2nY
��tr���9/1�����z{R�����T�z�^BV��������v�������%�I�
��v�mt�:��x�4;��/>��"dn5kS��=�F%��~/o�P���]���&U0�4����Eg�	�mT">��i����c������5�����f�`����}LN�6Z��ex��fZ���Fnk����&e�����*����~�v���0���RS��Y�i0��7@/�|��{7��;�$4�����d7#���*�7E�w�t_�p��|���0�\^&�Su�\�|��U&#�Df�h	I�P6��(u�����x�
���z�,������!����"��/c��2���������^y�P���W�>2�de*���Ja:OEl�6�
UX4�d}��]j�8��%��4,K*3 ���I�Z�����3���~��5�;9���b�[f��LD�����c]�	 ].0�}����K�-��:��U�V����
�Y*�mx�"7��*��t(���57$���g�0L]~T�o��*Z��a�bk��?e�ifL�oi��P>���Js������*<�\�GJ���#bF���G(Z�t�������?��J}���o��������.�I�8�.��z.�e}%�v;�U=�V�w��s�h�pv�]\�~}�������'Y�w���$�{+�u�����^x�[���w���@=�}C�]�^���?Y�H*�M������������X��Zd����{�_$�r ����H��C�/����r#�M<I�c��L����/jv�Z��-�s�s~��G��H	������.����~�l�s�M�'�(�S��?��������c*�@k��#|jB/��+��9�4 >H*�?BA>�,�����RE3?�o6��;�8
�M����#�E^�n�7�/s^o4!��-	�H��?~
��&|
#2Thom Brown
thombrown@gmail.com
In reply to: Dimitri Fontaine (#1)
1 attachment(s)
Re: Command Triggers, v16

On 15 March 2012 18:13, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Hi,

I guess it's time to start a new thread here. Please find attached
version 16 of the command trigger patch, with augmented documentation
and “magic variable” support (TG_WHEN, TG_OBJECTID and such).

The current version of the patch only supports PLpgSQL, I need to add
support for the other languages in core but I though Thom would like to
be able to play with a new patch before I finish plpython, plperl and
pltcl support.

This patch also includes edits following latest reviews from both Thom,
Andres and Robert, in particular ANY command triggers are now called
from the same place as specific command triggers and receive the same
parameters.

Good to see that ANY COMMAND triggers contain everything the specific
triggers have. I've completed a complete re-run of all my testing.

Note: incremental patch attached for the following section...

-----START----

The docs have an excessive opening <varlistentry> tag. The docs also
list ALTER CAST as an option, which it isn't. There's an old version
of a paragraph included, immediately followed by its revised version.
It begins with "Triggers on ANY command...".

The example given for the abort_any_command function has a typo. The
RAISE statement should have a comma after the closing single quote
instead of %.

In doc/src/sgml/plpgsql.sgml:

“The command trigger function return's value is not used.”
should be
“The command trigger function’s return value is not used.”

“This example trigger just raise a...”
should be
“This example trigger just raises a...”

The example procedure isn't called correctly in the create command
trigger statement below it. It refers to it at "any_snitch", but the
function is just named "snitch". Also the style is inconsistent with
the other trigger functions further up the page, such as putting the
function language last, showing the return type on the same line as
the CREATE FUNCTION line and using upper-case lettering for keywords.

I don’t understand how functions can return a type of “command
trigger”. This certainly works, but I’ve never seen a type consisting
of more than one word. Could you explain this for me? This is also
at odds with the error message in src/backend/commands/cmdtrigger.c:

errmsg("function \"%s\" must return type \"trigger\"",

Should be “command trigger” as a regular trigger can’t be used on
command triggers.

----END----

At this moment in time, CTAS is still outstanding. Is the plan to try
to get that in for this release, or as an enhancement in 9.3?

I don’t know if this was a problem before that I didn’t spot
(probably), but triggers for both ANY COMMAND and ALTER FOREIGN TABLE
show a command tag of ALTER TABLE for ALTER FOREIGN TABLE statements
where the column is renamed:

thom@test=# ALTER FOREIGN TABLE test.dict2 RENAME COLUMN word TO words;
NOTICE: Command trigger on any: tg_when='BEFORE' cmd_tag='ALTER
TABLE' objectid=16569 schemaname='test' objectname='dict2'
NOTICE: Command trigger: tg_when='BEFORE' cmd_tag='ALTER TABLE'
objectid=16569 schemaname='test' objectname='dict2'
NOTICE: Command trigger: tg_when='AFTER' cmd_tag='ALTER TABLE'
objectid=16569 schemaname='test' objectname='dict2'
NOTICE: Command trigger on any: tg_when='AFTER' cmd_tag='ALTER TABLE'
objectid=16569 schemaname='test' objectname='dict2'
ALTER TABLE

I don’t think this is the fault of the trigger code because it
actually says ALTER TABLE at the bottom, suggesting it’s something
already present. This isn’t the case when adding or dropping columns.
Any comments?

Altering the properties of a function (such as cost, security definer,
whether it’s stable etc) doesn’t report the function’s OID:

thom@test=# ALTER FUNCTION test.testfunc2() COST 77;
NOTICE: Command trigger on any: tg_when='BEFORE' cmd_tag='ALTER
FUNCTION' objectid=<NULL> schemaname='test' objectname='testfunc2'
NOTICE: Command trigger: tg_when='BEFORE' cmd_tag='ALTER FUNCTION'
objectid=<NULL> schemaname='test' objectname='testfunc2'
NOTICE: Command trigger: tg_when='AFTER' cmd_tag='ALTER FUNCTION'
objectid=<NULL> schemaname='test' objectname='testfunc2'
NOTICE: Command trigger on any: tg_when='AFTER' cmd_tag='ALTER
FUNCTION' objectid=<NULL> schemaname='test' objectname='testfunc2'
ALTER FUNCTION

I get a garbage objectname for AFTER ANY COMMAND triggers on ALTER
TEXT SEARCH DICTIONARY when changing its options. It doesn’t show it
in the below example because I can’t get it displaying in plain text,
but where the objectname is blank is where I’m seeing unicode a square
containing “0074” 63 times in a row:

thom@test=# ALTER TEXT SEARCH DICTIONARY testnew.test_stem2 (
StopWords = dutch );
NOTICE: Command trigger on any: tg_when='BEFORE' cmd_tag='ALTER TEXT
SEARCH DICTIONARY' objectid=16617 schemaname='testnew'
objectname='test_stem2'
NOTICE: Command trigger: tg_when='BEFORE' cmd_tag='ALTER TEXT SEARCH
DICTIONARY' objectid=16617 schemaname='testnew'
objectname='test_stem2'
NOTICE: Command trigger: tg_when='AFTER' cmd_tag='ALTER TEXT SEARCH
DICTIONARY' objectid=16617 schemaname='testnew'
objectname='test_stem2'
NOTICE: Command trigger on any: tg_when='AFTER' cmd_tag='ALTER TEXT
SEARCH DICTIONARY' objectid=16617 schemaname='testnew'
objectname=' '
ALTER TEXT SEARCH DICTIONARY

Specific command triggers on ALTER VIEW don’t work at all:

thom@test=# ALTER VIEW view_test OWNER TO test;
NOTICE: Command trigger on any: tg_when='BEFORE' cmd_tag='ALTER VIEW'
objectid=16625 schemaname='public' objectname='view_test'
NOTICE: Command trigger on any: tg_when='AFTER' cmd_tag='ALTER VIEW'
objectid=16625 schemaname='public' objectname='view_test'
ALTER VIEW

Command triggers that fire for CREATE RULE show a schema, but DROP
RULE doesn’t. Which is it?:

thom@test=# CREATE RULE notify_test AS ON UPDATE TO seq_table DO ALSO
NOTIFY test; -- support for testing DROP RULE
NOTICE: Command trigger on any: tg_when='BEFORE' cmd_tag='CREATE
RULE' objectid=<NULL> schemaname='public' objectname='notify_test'
NOTICE: Command trigger: tg_when='BEFORE' cmd_tag='CREATE RULE'
objectid=<NULL> schemaname='public' objectname='notify_test'
NOTICE: Command trigger: tg_when='AFTER' cmd_tag='CREATE RULE'
objectid=16706 schemaname='public' objectname='notify_test'
NOTICE: Command trigger on any: tg_when='AFTER' cmd_tag='CREATE RULE'
objectid=16706 schemaname='public' objectname='notify_test'
CREATE RULE
thom@test=# DROP RULE notify_test ON seq_table;
NOTICE: Command trigger on any: tg_when='BEFORE' cmd_tag='DROP RULE'
objectid=16706 schemaname='<NULL>' objectname='notify_test'
NOTICE: Command trigger: tg_when='BEFORE' cmd_tag='DROP RULE'
objectid=16706 schemaname='<NULL>' objectname='notify_test'
NOTICE: Command trigger: tg_when='AFTER' cmd_tag='DROP RULE'
objectid=<NULL> schemaname='<NULL>' objectname='notify_test'
NOTICE: Command trigger on any: tg_when='AFTER' cmd_tag='DROP RULE'
objectid=<NULL> schemaname='<NULL>' objectname='notify_test'
DROP RULE

This same behaviour exists for DROP TRIGGER.

Regards

Thom

Attachments:

command_triggers_v16_corrections.patchtext/x-patch; charset=US-ASCII; name=command_triggers_v16_corrections.patchDownload
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index f5f2079..13c8c81 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -3933,20 +3933,19 @@ SELECT * FROM sales_summary_bytime;
    <title>Triggers on commands</title>
 
    <para>
-    <application>PL/pgSQL</application> can be used to define trigger
-    procedures. A trigger procedure is created with the
+    <application>PL/pgSQL</application> can be used to define command 
+    trigger procedures. A command trigger procedure is created with the
     <command>CREATE FUNCTION</> command, declaring it as a function with
     no arguments and a return type of <type>command trigger</type>.
    </para>
 
   <para>
    When a <application>PL/pgSQL</application> function is called as a
-   trigger, several special variables are created automatically in the
-   top-level block. They are:
+   command trigger, several special variables are created automatically
+   in the top-level block. They are:
 
    <variablelist>
     <varlistentry>
-    <varlistentry>
      <term><varname>TG_TAG</varname></term>
      <listitem>
       <para>
@@ -4002,7 +4001,7 @@ SELECT * FROM sales_summary_bytime;
   </para>
 
   <para>
-   The command trigger function return's value is not used.
+   The command trigger function's return value is not used.
   </para>
 
    <para>
@@ -4014,23 +4013,20 @@ SELECT * FROM sales_summary_bytime;
     <title>A <application>PL/pgSQL</application> Command Trigger Procedure</title>
 
     <para>
-     This example trigger just raise a <literal>NOTICE</literal> message
+     This example trigger simply raises a <literal>NOTICE</literal> message
      each time a supported command is executed.
     </para>
 
 <programlisting>
-create or replace function snitch()
- returns command trigger
- language plpgsql
-as $$
-begin
-  raise notice 'snitch: % % %.% [%]',
+CREATE OR REPLACE FUNCTION snitch() RETURNS command trigger AS $$
+BEGIN
+    RAISE NOTICE 'snitch: % % %.% [%]',
                tg_when, tg_tag, tg_schemaname, tg_objectname, tg_objectid;
-end;
-$$;
+END;
+$$ LANGUAGE plpgsql;
 
-create command trigger snitch_before before any command execute procedure any_snitch();
-create command trigger snitch_after after any command execute procedure any_snitch();
+CREATE COMMAND TRIGGER snitch_before BEFORE ANY COMMAND EXECUTE PROCEDURE snitch();
+CREATE COMMAND TRIGGER snitch_after AFTER ANY COMMAND EXECUTE PROCEDURE snitch();
 </programlisting>
    </example>
   </sect2>
diff --git a/doc/src/sgml/ref/create_command_trigger.sgml b/doc/src/sgml/ref/create_command_trigger.sgml
index fc12d2e..01c7826 100644
--- a/doc/src/sgml/ref/create_command_trigger.sgml
+++ b/doc/src/sgml/ref/create_command_trigger.sgml
@@ -30,7 +30,6 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
 <phrase>where <replaceable class="parameter">command</replaceable> can be one of:</phrase>
 
     ALTER AGGREGATE
-    ALTER CAST
     ALTER COLLATION
     ALTER CONVERSION
     ALTER DOMAIN
@@ -56,6 +55,7 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
     ALTER VIEW
     CLUSTER
     CREATE AGGREGATE
+    CREATE CAST
     CREATE COLLATION
     CREATE CONVERSION
     CREATE DOMAIN
@@ -186,14 +186,12 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
       That leaves out the following list of non supported commands.
      </para>
      <para>
-      Commands that refers to global objects, such as databases, tablespaces
-      and roles are not supported. As command triggers are per-database, it
-      would be weird to affect e.g. a tablespace depending on which database
-      you are connected to.
+      Commands that refer to global objects, such as databases, tablespaces
+      and roles, are not supported.
      </para>
      <para>
       Commands that exercise their own transaction control are only
-      supported in <literal>BEFORE</literal> command triggers, that's the
+      supported in <literal>BEFORE</literal> command triggers.  This is the
       case for <literal>VACUUM</literal>, <literal>CLUSTER</literal>,
       <literal>CREATE INDEX CONCURRENTLY</literal>, and <literal>REINDEX
       DATABASE</literal>.
@@ -220,11 +218,6 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
       not to be able to take over control from a superuser.
      </para>
      <para>
-      Triggers on ANY command support more commands than just this list, and
-      will provide NULL values for every argument except for the argument
-      that determines whether the trigger was before or after the command
-      event, and the command tag.
-
       Triggers on <literal>ANY</literal> command support more commands than
       just this list, and will only provide the <literal>command
       tag</literal> argument as <literal>NOT NULL</literal>. Supporting more
@@ -238,12 +231,12 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
     <term><replaceable class="parameter">function_name</replaceable></term>
     <listitem>
      <para>
-      A user-supplied function that is declared as taking 5 arguments of
-      type text, text, oid, text, text and returning void.
+      A user-supplied function that is declared as taking no argument and
+      returning type <literal>command trigger</literal>.
      </para>
      <para>
       If your command trigger is implemented in <literal>C</literal> then it
-      will be called with yet another argument, of
+      will be called with an argument, of
       type <literal>internal</literal>, which is a pointer to
       the <literal>Node *</literal> parse tree.
      </para>
@@ -275,7 +268,7 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
 CREATE OR REPLACE FUNCTION abort_any_command()
  RETURNS command trigger LANGUAGE plpgsql AS $$
 BEGIN
-  RAISE EXCEPTION 'command % is disabled' % tg_tag;
+  RAISE EXCEPTION 'command % is disabled', tg_tag;
 END;
 $$;
 
diff --git a/src/backend/commands/cmdtrigger.c b/src/backend/commands/cmdtrigger.c
index 6f134d5..f06f6b9 100644
--- a/src/backend/commands/cmdtrigger.c
+++ b/src/backend/commands/cmdtrigger.c
@@ -191,7 +191,7 @@ CreateCmdTrigger(CreateCmdTrigStmt *stmt, const char *queryString)
 	if (funcrettype != CMDTRIGGEROID)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-				 errmsg("function \"%s\" must return type \"trigger\"",
+				 errmsg("function \"%s\" must return type \"command trigger\"",
 						NameListToString(stmt->funcname))));
 
 	trigoid = InsertCmdTriggerTuple(tgrel, stmt->command, stmt->trigname,
#3Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Thom Brown (#2)
Re: Command Triggers, v16

Thanks for testing this new version (again).

A quick answer now, I'll send another patch tomorrow.

Thom Brown <thombrown@gmail.com> writes:

I don’t understand how functions can return a type of “command
trigger”. This certainly works, but I’ve never seen a type consisting
of more than one word. Could you explain this for me? This is also

I tricked that in the grammar, the type is called cmdtrigger but I
though it wouldn't be a good choice for the SQL statement.

at odds with the error message in src/backend/commands/cmdtrigger.c:

errmsg("function \"%s\" must return type \"trigger\"",

I realized I needed another trigger like data type after I had worked
this message, I need to get back on it, thanks.

At this moment in time, CTAS is still outstanding. Is the plan to try
to get that in for this release, or as an enhancement in 9.3?

The plan is to get CTAS as a utility command in 9.2 then update the
command trigger patch to benefit from the new situation. We've been
wondering about making its own commit fest entry for that patch, it's
now clear in my mind, that needs to happen.

Stay tuned, follow up email due tomorrow.
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#4Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Dimitri Fontaine (#3)
Re: Command Triggers, v16

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

At this moment in time, CTAS is still outstanding. Is the plan to try
to get that in for this release, or as an enhancement in 9.3?

The plan is to get CTAS as a utility command in 9.2 then update the
command trigger patch to benefit from the new situation. We've been
wondering about making its own commit fest entry for that patch, it's
now clear in my mind, that needs to happen.

https://commitfest.postgresql.org/action/patch_view?id=823

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#5Thom Brown
thombrown@gmail.com
In reply to: Dimitri Fontaine (#4)
Re: Command Triggers, v16

On 15 March 2012 22:06, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

At this moment in time, CTAS is still outstanding.  Is the plan to try
to get that in for this release, or as an enhancement in 9.3?

The plan is to get CTAS as a utility command in 9.2 then update the
command trigger patch to benefit from the new situation. We've been
wondering about making its own commit fest entry for that patch, it's
now clear in my mind, that needs to happen.

 https://commitfest.postgresql.org/action/patch_view?id=823

Looks like the ctas-on-command-triggers-01.patch patch needs re-basing.

Thom

#6Andres Freund
andres@anarazel.de
In reply to: Thom Brown (#5)
Re: Command Triggers, v16

On Thursday, March 15, 2012 11:41:21 PM Thom Brown wrote:

On 15 March 2012 22:06, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

At this moment in time, CTAS is still outstanding. Is the plan to try
to get that in for this release, or as an enhancement in 9.3?

The plan is to get CTAS as a utility command in 9.2 then update the
command trigger patch to benefit from the new situation. We've been
wondering about making its own commit fest entry for that patch, it's
now clear in my mind, that needs to happen.

https://commitfest.postgresql.org/action/patch_view?id=823

Looks like the ctas-on-command-triggers-01.patch patch needs re-basing.

I can do that - but imo the other patch (not based on the command triggers
stuff) is the relevant for now as this patch ought to be applied before
command triggers. It doesn't seem to make too much sense to rebase it
frequently as long as the command triggers patch isn't stable...

Any reason you would prefer it being rebased?

Andres

#7Christian Ullrich
chris@chrullrich.net
In reply to: Thom Brown (#2)
Re: Command Triggers, v16

* Thom Brown wrote:

I don�t understand how functions can return a type of �command
trigger�. This certainly works, but I�ve never seen a type consisting
of more than one word. Could you explain this for me? This is also

postgres=> with types (name) as
postgres-> (select format_type(oid, NULL) from pg_type)
postgres-> select name from types where name like '% %'
postgres-> and not name like '%[]';
name
-----------------------------
double precision
character varying
time without time zone
timestamp without time zone
timestamp with time zone
time with time zone
bit varying
(7 Zeilen)

I think these are all specially handled in the parser.

--
Christian Ullrich

#8Thom Brown
thombrown@gmail.com
In reply to: Andres Freund (#6)
Re: Command Triggers, v16

On 16 March 2012 08:13, Andres Freund <andres@anarazel.de> wrote:

On Thursday, March 15, 2012 11:41:21 PM Thom Brown wrote:

Looks like the ctas-on-command-triggers-01.patch patch needs re-basing.

I can do that - but imo the other patch (not based on the command triggers
stuff) is the relevant for now as this patch ought to be applied before
command triggers. It doesn't seem to make too much sense to rebase it
frequently as long as the command triggers patch isn't stable...

Any reason you would prefer it being rebased?

Using latest Git master without any additional patches, I can't get it to apply:

Hunk #1 FAILED at 16.
Hunk #2 succeeded at 22 (offset -1 lines).
1 out of 2 hunks FAILED -- saving rejects to file
src/include/commands/tablecmds.h.rej

Thom

#9Andres Freund
andres@anarazel.de
In reply to: Dimitri Fontaine (#3)
Re: Command Triggers, v16

Hi,

On Thursday, March 15, 2012 10:58:49 PM Dimitri Fontaine wrote:

I tricked that in the grammar, the type is called cmdtrigger but I
though it wouldn't be a good choice for the SQL statement.

Hm. I am decidedly unhappy with that grammar hackery... But then maybe I am
squeamish.

+ oid  |  typname   | oid  |  proname   
+------+------------+------+------------
+ 1790 | refcursor  |   46 | textin
+ 3838 | cmdtrigger | 2300 | trigger_in
+(2 rows)

Hm. Wonder if its a good idea to reuse trigger_in. So far we have duplicated
functions for that.

@@ -482,12 +494,21 @@ ListCommandTriggers(CommandContext cmd)

switch (form->ctgtype)
{

case CMD_TRIGGER_FIRED_BEFORE:
-               cmd->before = lappend_oid(cmd->before, form->ctgfoid);
+           {
+               if (list_any_triggers)
+                   cmd->before_any = lappend_oid(cmd->before_any,
form->ctgfoid); +               else
+                   cmd->before = lappend_oid(cmd->before, form->ctgfoid);

break;

-
...
+       case CMD_TRIGGER_FIRED_BEFORE:
+       {
+           whenstr = "BEFORE";
+
+           foreach(cell, cmd->before_any)
+           {
+               Oid proc = lfirst_oid(cell);
+
+               call_cmdtrigger_procedure(cmd, (RegProcedure)proc,
whenstr); +           }
+           foreach(cell, cmd->before)
+           {
+               Oid proc = lfirst_oid(cell);
+
+               call_cmdtrigger_procedure(cmd, (RegProcedure)proc,
whenstr); +           }
+           break;
+       }

This will have the effect of calling triggers outside of alphabetic order. I
don't think thats a good idea even if one part is ANY and the other a specific
command.
I don't think there is any reason anymore to separate the two? The only
callsite seems to look like:

632- default:
633: ListCommandTriggers(cmd, true); /* list ANY command triggers */
634: ListCommandTriggers(cmd, false); /* and triggers for this
command tag */

Andres

#10Andres Freund
andres@anarazel.de
In reply to: Thom Brown (#8)
Re: Command Triggers, v16

On Friday, March 16, 2012 09:30:58 AM Thom Brown wrote:

On 16 March 2012 08:13, Andres Freund <andres@anarazel.de> wrote:

On Thursday, March 15, 2012 11:41:21 PM Thom Brown wrote:

Looks like the ctas-on-command-triggers-01.patch patch needs re-basing.

I can do that - but imo the other patch (not based on the command
triggers stuff) is the relevant for now as this patch ought to be
applied before command triggers. It doesn't seem to make too much sense
to rebase it frequently as long as the command triggers patch isn't
stable...

Any reason you would prefer it being rebased?

Using latest Git master without any additional patches, I can't get it to
apply:

Hunk #1 FAILED at 16.
Hunk #2 succeeded at 22 (offset -1 lines).
1 out of 2 hunks FAILED -- saving rejects to file
src/include/commands/tablecmds.h.rej

Did you read the paragraph above?

Andres

#11Thom Brown
thombrown@gmail.com
In reply to: Dimitri Fontaine (#3)
Re: Command Triggers, v16

On 15 March 2012 21:58, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Thom Brown <thombrown@gmail.com> writes:

I don’t understand how functions can return a type of “command
trigger”.  This certainly works, but I’ve never seen a type consisting
of more than one word.  Could you explain this for me?  This is also

I tricked that in the grammar, the type is called cmdtrigger but I
though it wouldn't be a good choice for the SQL statement.

Christian sent me a message mentioning that we've pretty much always
had data types consisting of more than one word (e.g. timestamp
without time zone). So I completely retract my question as it's
obviously nonsense.

Thom

#12Thom Brown
thombrown@gmail.com
In reply to: Andres Freund (#10)
Re: Command Triggers, v16

On 16 March 2012 08:45, Andres Freund <andres@anarazel.de> wrote:

On Friday, March 16, 2012 09:30:58 AM Thom Brown wrote:

On 16 March 2012 08:13, Andres Freund <andres@anarazel.de> wrote:

On Thursday, March 15, 2012 11:41:21 PM Thom Brown wrote:

Looks like the ctas-on-command-triggers-01.patch patch needs re-basing.

I can do that - but imo the other patch (not based on the command
triggers stuff) is the relevant for now as this patch ought to be
applied before command triggers. It doesn't seem to make too much sense
to rebase it frequently as long as the command triggers patch isn't
stable...

Any reason you would prefer it being rebased?

Using latest Git master without any additional patches, I can't get it to
apply:

Hunk #1 FAILED at 16.
Hunk #2 succeeded at 22 (offset -1 lines).
1 out of 2 hunks FAILED -- saving rejects to file
src/include/commands/tablecmds.h.rej

Did you read the paragraph above?

Yes, but I don't think I'm clear on what you mean. Are you saying I
should use ctas-01.patch instead of ctas-on-command-triggers-01.patch?
If so, that patch results in me not being able to apply Dimitri's
command triggers patch. And I thought that patch doesn't actually
cause triggers to fire on CTAS?

Thom

#13Andres Freund
andres@anarazel.de
In reply to: Thom Brown (#12)
Re: Command Triggers, v16

On Friday, March 16, 2012 09:55:10 AM Thom Brown wrote:

On 16 March 2012 08:45, Andres Freund <andres@anarazel.de> wrote:

On Friday, March 16, 2012 09:30:58 AM Thom Brown wrote:

On 16 March 2012 08:13, Andres Freund <andres@anarazel.de> wrote:

On Thursday, March 15, 2012 11:41:21 PM Thom Brown wrote:

Looks like the ctas-on-command-triggers-01.patch patch needs
re-basing.

I can do that - but imo the other patch (not based on the command
triggers stuff) is the relevant for now as this patch ought to be
applied before command triggers. It doesn't seem to make too much
sense to rebase it frequently as long as the command triggers patch
isn't stable...

Any reason you would prefer it being rebased?

Using latest Git master without any additional patches, I can't get it
to apply:

Hunk #1 FAILED at 16.
Hunk #2 succeeded at 22 (offset -1 lines).
1 out of 2 hunks FAILED -- saving rejects to file
src/include/commands/tablecmds.h.rej

Did you read the paragraph above?

Yes, but I don't think I'm clear on what you mean. Are you saying I
should use ctas-01.patch instead of ctas-on-command-triggers-01.patch?
If so, that patch results in me not being able to apply Dimitri's
command triggers patch. And I thought that patch doesn't actually
cause triggers to fire on CTAS?

Well. Why do you want to apply them concurrently? As far as I understand the
plan is to get ctas-as-utility merged with master and then let dim rebase the
ddl trigger patch.
The ctas-as-utility stuff imo is worthy of being applied independently of DDL
triggers. The current duplication in the code lead to multiple bugs already.

Andres

#14Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Andres Freund (#9)
Re: Command Triggers, v16

Andres Freund <andres@anarazel.de> writes:

On Thursday, March 15, 2012 10:58:49 PM Dimitri Fontaine wrote:

I tricked that in the grammar, the type is called cmdtrigger but I
though it wouldn't be a good choice for the SQL statement.

Hm. I am decidedly unhappy with that grammar hackery... But then maybe I am
squeamish.

It's easy to remove that hack and get back to having the user visible
type be cmdtrigger, but as this type only serves as a marker for PL
compiling function (validate handler) I though having a user friendly
name was important here.

+ oid  |  typname   | oid  |  proname
+------+------------+------+------------
+ 1790 | refcursor  |   46 | textin
+ 3838 | cmdtrigger | 2300 | trigger_in
+(2 rows)

Hm. Wonder if its a good idea to reuse trigger_in. So far we have duplicated
functions for that.

Again, if we think the use case warrants duplicating code rather than
playing with the type definition, I will do that.

This will have the effect of calling triggers outside of alphabetic order. I
don't think thats a good idea even if one part is ANY and the other a specific
command.
I don't think there is any reason anymore to separate the two? The only
callsite seems to look like:

The idea is to have a predictable ordering of command triggers. The code
changed in the patch v16 (you pasted code from git in between v15 and
v16, I cleaned it up) and is now easier to read:

case CMD_TRIGGER_FIRED_BEFORE:
whenstr = "BEFORE";
procs[0] = cmd->before_any;
procs[1] = cmd->before;
break;

case CMD_TRIGGER_FIRED_AFTER:
whenstr = "AFTER";
procs[0] = cmd->after;
procs[1] = cmd->after_any;
break;

So it's BEFORE ANY then BEFORE command then AFTER command then AFTER
ANY. That's an arbitrary I made and we can easily reconsider. Triggers
are called in alphabetical order in each “slot” here.

In my mind it makes sense to have ANY triggers around the specific
triggers, but it's hard to explain why that feels better.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#15Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Thom Brown (#2)
1 attachment(s)
Re: Command Triggers, v16

Thom Brown <thombrown@gmail.com> writes:

Note: incremental patch attached for the following section...

Applied, thanks!

I don’t know if this was a problem before that I didn’t spot
(probably), but triggers for both ANY COMMAND and ALTER FOREIGN TABLE
show a command tag of ALTER TABLE for ALTER FOREIGN TABLE statements
where the column is renamed:

I don’t think this is the fault of the trigger code because it
actually says ALTER TABLE at the bottom, suggesting it’s something
already present. This isn’t the case when adding or dropping columns.
Any comments?

We're building command trigger on top of the existing code. From the
grammar we can see that an alter table and an alter foreign table are
processed as the same command.

AlterForeignTableStmt:
ALTER FOREIGN TABLE relation_expr alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);

So while I think we could want to revisit that choice down the road, I
don't think that's for the command triggers patch to do it.

Altering the properties of a function (such as cost, security definer,
whether it’s stable etc) doesn’t report the function’s OID:

That's now fixed. I've checked that all the other places where we're
saying objectId = InvalidOid are related to before create or after drop
commands.

I get a garbage objectname for AFTER ANY COMMAND triggers on ALTER
TEXT SEARCH DICTIONARY when changing its options. It doesn’t show it
in the below example because I can’t get it displaying in plain text,
but where the objectname is blank is where I’m seeing unicode a square
containing “0074” 63 times in a row:

I couldn't reproduce, but I've spotted the problem in the source, and
fixed it. I could find a couple other places that should have been using
pstrdup(NameStr(…)) too, and fixed them. I added a test.

Specific command triggers on ALTER VIEW don’t work at all:

Can't reproduce, and that's already part of the regression tests.

Command triggers that fire for CREATE RULE show a schema, but DROP
RULE doesn’t. Which is it?:

Oh, both RULE and TRIGGER are not qualified, and I was filling the
schemaname with the schema of the relation they refer to in the CREATE
command, and had DROP correctly handling the TRIGGER case.

That's now fixed, schemaname is NULL in all cases here.

You can read the changes here:

https://github.com/dimitri/postgres/compare/5e8e37922d...144d870162

And I've been attaching an incremental patch too. Next patch revision is
expected later today with support for plpython, plperl and pltcl.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

Attachments:

cmdtrigger-thomsreview-20120316.patchtext/x-patchDownload
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index f5f2079..5f84751 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -3933,20 +3933,19 @@ SELECT * FROM sales_summary_bytime;
    <title>Triggers on commands</title>
 
    <para>
-    <application>PL/pgSQL</application> can be used to define trigger
-    procedures. A trigger procedure is created with the
+    <application>PL/pgSQL</application> can be used to define command
+    trigger procedures. A command trigger procedure is created with the
     <command>CREATE FUNCTION</> command, declaring it as a function with
     no arguments and a return type of <type>command trigger</type>.
    </para>
 
   <para>
    When a <application>PL/pgSQL</application> function is called as a
-   trigger, several special variables are created automatically in the
-   top-level block. They are:
+   command trigger, several special variables are created automatically
+   in the top-level block. They are:
 
    <variablelist>
     <varlistentry>
-    <varlistentry>
      <term><varname>TG_TAG</varname></term>
      <listitem>
       <para>
@@ -4002,7 +4001,7 @@ SELECT * FROM sales_summary_bytime;
   </para>
 
   <para>
-   The command trigger function return's value is not used.
+   The command trigger function's return value is not used.
   </para>
 
    <para>
@@ -4014,23 +4013,20 @@ SELECT * FROM sales_summary_bytime;
     <title>A <application>PL/pgSQL</application> Command Trigger Procedure</title>
 
     <para>
-     This example trigger just raise a <literal>NOTICE</literal> message
+     This example trigger simply raises a <literal>NOTICE</literal> message
      each time a supported command is executed.
     </para>
 
 <programlisting>
-create or replace function snitch()
- returns command trigger
- language plpgsql
-as $$
-begin
-  raise notice 'snitch: % % %.% [%]',
+CREATE OR REPLACE FUNCTION snitch() RETURNS command trigger AS $$
+BEGIN
+    RAISE NOTICE 'snitch: % % %.% [%]',
                tg_when, tg_tag, tg_schemaname, tg_objectname, tg_objectid;
-end;
-$$;
+END;
+$$ LANGUAGE plpgsql;
 
-create command trigger snitch_before before any command execute procedure any_snitch();
-create command trigger snitch_after after any command execute procedure any_snitch();
+CREATE COMMAND TRIGGER snitch_before BEFORE ANY COMMAND EXECUTE PROCEDURE snitch();
+CREATE COMMAND TRIGGER snitch_after AFTER ANY COMMAND EXECUTE PROCEDURE snitch();
 </programlisting>
    </example>
   </sect2>
diff --git a/doc/src/sgml/ref/create_command_trigger.sgml b/doc/src/sgml/ref/create_command_trigger.sgml
index fc12d2e..01c7826 100644
--- a/doc/src/sgml/ref/create_command_trigger.sgml
+++ b/doc/src/sgml/ref/create_command_trigger.sgml
@@ -30,7 +30,6 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
 <phrase>where <replaceable class="parameter">command</replaceable> can be one of:</phrase>
 
     ALTER AGGREGATE
-    ALTER CAST
     ALTER COLLATION
     ALTER CONVERSION
     ALTER DOMAIN
@@ -56,6 +55,7 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
     ALTER VIEW
     CLUSTER
     CREATE AGGREGATE
+    CREATE CAST
     CREATE COLLATION
     CREATE CONVERSION
     CREATE DOMAIN
@@ -186,14 +186,12 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
       That leaves out the following list of non supported commands.
      </para>
      <para>
-      Commands that refers to global objects, such as databases, tablespaces
-      and roles are not supported. As command triggers are per-database, it
-      would be weird to affect e.g. a tablespace depending on which database
-      you are connected to.
+      Commands that refer to global objects, such as databases, tablespaces
+      and roles, are not supported.
      </para>
      <para>
       Commands that exercise their own transaction control are only
-      supported in <literal>BEFORE</literal> command triggers, that's the
+      supported in <literal>BEFORE</literal> command triggers.  This is the
       case for <literal>VACUUM</literal>, <literal>CLUSTER</literal>,
       <literal>CREATE INDEX CONCURRENTLY</literal>, and <literal>REINDEX
       DATABASE</literal>.
@@ -220,11 +218,6 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
       not to be able to take over control from a superuser.
      </para>
      <para>
-      Triggers on ANY command support more commands than just this list, and
-      will provide NULL values for every argument except for the argument
-      that determines whether the trigger was before or after the command
-      event, and the command tag.
-
       Triggers on <literal>ANY</literal> command support more commands than
       just this list, and will only provide the <literal>command
       tag</literal> argument as <literal>NOT NULL</literal>. Supporting more
@@ -238,12 +231,12 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
     <term><replaceable class="parameter">function_name</replaceable></term>
     <listitem>
      <para>
-      A user-supplied function that is declared as taking 5 arguments of
-      type text, text, oid, text, text and returning void.
+      A user-supplied function that is declared as taking no argument and
+      returning type <literal>command trigger</literal>.
      </para>
      <para>
       If your command trigger is implemented in <literal>C</literal> then it
-      will be called with yet another argument, of
+      will be called with an argument, of
       type <literal>internal</literal>, which is a pointer to
       the <literal>Node *</literal> parse tree.
      </para>
@@ -275,7 +268,7 @@ CREATE COMMAND TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFOR
 CREATE OR REPLACE FUNCTION abort_any_command()
  RETURNS command trigger LANGUAGE plpgsql AS $$
 BEGIN
-  RAISE EXCEPTION 'command % is disabled' % tg_tag;
+  RAISE EXCEPTION 'command % is disabled', tg_tag;
 END;
 $$;
 
diff --git a/src/backend/commands/cmdtrigger.c b/src/backend/commands/cmdtrigger.c
index 6f134d5..f06f6b9 100644
--- a/src/backend/commands/cmdtrigger.c
+++ b/src/backend/commands/cmdtrigger.c
@@ -191,7 +191,7 @@ CreateCmdTrigger(CreateCmdTrigStmt *stmt, const char *queryString)
 	if (funcrettype != CMDTRIGGEROID)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-				 errmsg("function \"%s\" must return type \"trigger\"",
+				 errmsg("function \"%s\" must return type \"command trigger\"",
 						NameListToString(stmt->funcname))));
 
 	trigoid = InsertCmdTriggerTuple(tgrel, stmt->command, stmt->trigname,
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
index a18b0bb..87d4ca3 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -297,6 +297,7 @@ get_object_name(CommandContext cmd, ObjectType objtype,
 		case OBJECT_CAST:
 			cmd->objectname = NULL;
 			break;
+		case OBJECT_RULE:
 		case OBJECT_TRIGGER:
 			cmd->objectname = pstrdup(strVal(llast(objname)));
 			break;
@@ -313,7 +314,6 @@ get_object_name(CommandContext cmd, ObjectType objtype,
 		case OBJECT_OPERATOR:
 		case OBJECT_LANGUAGE:
 		case OBJECT_CMDTRIGGER:
-		case OBJECT_RULE:
 		case OBJECT_FDW:
 		case OBJECT_FOREIGN_SERVER:
 		case OBJECT_OPCLASS:
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index a87feca..ce97b8f 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1399,6 +1399,19 @@ AlterFunction(AlterFunctionStmt *stmt)
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("ROWS is not applicable when function does not return a set")));
 	}
+
+	/* Call BEFORE ALTER FUNCTION command triggers */
+	InitCommandContext(&cmd, (Node *)stmt);
+
+	if (CommandFiresTriggers(&cmd))
+	{
+		cmd.objectId = HeapTupleGetOid(tup);
+		cmd.objectname = pstrdup(NameStr(procForm->proname));
+		cmd.schemaname = get_namespace_name(procForm->pronamespace);
+
+		ExecBeforeCommandTriggers(&cmd);
+	}
+
 	if (set_items)
 	{
 		Datum		datum;
@@ -1434,18 +1447,6 @@ AlterFunction(AlterFunctionStmt *stmt)
 								repl_val, repl_null, repl_repl);
 	}
 
-	/* Call BEFORE ALTER FUNCTION command triggers */
-	InitCommandContext(&cmd, (Node *)stmt);
-
-	if (CommandFiresTriggers(&cmd))
-	{
-		cmd.objectId = InvalidOid;
-		cmd.objectname = pstrdup(NameStr(procForm->proname));
-		cmd.schemaname = get_namespace_name(procForm->pronamespace);
-
-		ExecBeforeCommandTriggers(&cmd);
-	}
-
 	/* Do the update */
 	simple_heap_update(rel, &tup->t_self, tup);
 	CatalogUpdateIndexes(rel, tup);
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index c8dd6ce..f8c0c66 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -869,7 +869,7 @@ AlterOpFamily(AlterOpFamilyStmt *stmt)
 		opfForm = (Form_pg_opfamily) GETSTRUCT(htup);
 
 		cmd.objectId = opfamilyoid;
-		cmd.objectname = NameStr(opfForm->opfname);
+		cmd.objectname = pstrdup(NameStr(opfForm->opfname));
 		cmd.schemaname = get_namespace_name(opfForm->opfnamespace);
 
 		ReleaseSysCache(htup);
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 90b3525..f7f9a0e 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -437,7 +437,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 		{
 			cmd.objectId = InvalidOid;
 			cmd.objectname = stmt->trigname;
-			cmd.schemaname = get_namespace_name(RelationGetNamespace(rel));
+			cmd.schemaname = NULL; /* triggers are not schema qualified */
 
 			ExecBeforeCommandTriggers(&cmd);
 		}
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 7f473ca..fa69430 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -857,7 +857,7 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
 	{
 		Form_pg_ts_dict form = (Form_pg_ts_dict) GETSTRUCT(tup);
 		cmd.objectId = dictId;
-		cmd.objectname = NameStr(form->dictname);
+		cmd.objectname = pstrdup(NameStr(form->dictname));
 		cmd.schemaname = get_namespace_name(form->dictnamespace);
 
 		ExecBeforeCommandTriggers(&cmd);
@@ -1858,7 +1858,7 @@ AlterTSConfiguration(AlterTSConfigurationStmt *stmt)
 		Form_pg_ts_config form = (Form_pg_ts_config) GETSTRUCT(tup);
 
 		cmd.objectId = HeapTupleGetOid(tup);
-		cmd.objectname = NameStr(form->cfgname);
+		cmd.objectname = pstrdup(NameStr(form->cfgname));
 		cmd.schemaname = get_namespace_name(form->cfgnamespace);
 
 		ExecBeforeCommandTriggers(&cmd);
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 958367c..399f2e0 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -492,8 +492,7 @@ DefineQueryRewrite(char *rulename,
 	{
 		cmd->objectId = InvalidOid;
 		cmd->objectname = rulename;
-		cmd->schemaname =
-			get_namespace_name(RelationGetNamespace(event_relation));
+		cmd->schemaname = NULL;	/* rules are not schema qualified */
 
 		ExecBeforeCommandTriggers(cmd);
 	}
diff --git a/src/test/regress/expected/cmdtriggers.out b/src/test/regress/expected/cmdtriggers.out
index ee01e41..4c3fae8 100644
--- a/src/test/regress/expected/cmdtriggers.out
+++ b/src/test/regress/expected/cmdtriggers.out
@@ -449,9 +449,9 @@ NOTICE:  snitch: BEFORE any CREATE FUNCTION cmd.trigfunc
 NOTICE:  snitch: AFTER CREATE FUNCTION cmd.trigfunc
 NOTICE:  snitch: AFTER any CREATE FUNCTION cmd.trigfunc
 create trigger footg before update on cmd.foo for each row execute procedure cmd.trigfunc();
-NOTICE:  snitch: BEFORE any CREATE TRIGGER cmd.footg
-NOTICE:  snitch: BEFORE CREATE TRIGGER cmd.footg
-NOTICE:  snitch: AFTER any CREATE TRIGGER cmd.footg
+NOTICE:  snitch: BEFORE any CREATE TRIGGER <NULL>.footg
+NOTICE:  snitch: BEFORE CREATE TRIGGER <NULL>.footg
+NOTICE:  snitch: AFTER any CREATE TRIGGER <NULL>.footg
 alter trigger footg on cmd.foo rename to foo_trigger;
 NOTICE:  snitch: BEFORE any ALTER TRIGGER cmd.footg
 NOTICE:  snitch: BEFORE ALTER TRIGGER cmd.footg
@@ -494,6 +494,9 @@ create text search dictionary test_stem (
 NOTICE:  snitch: BEFORE any CREATE TEXT SEARCH DICTIONARY public.test_stem
 NOTICE:  snitch: AFTER CREATE TEXT SEARCH DICTIONARY public.test_stem
 NOTICE:  snitch: AFTER any CREATE TEXT SEARCH DICTIONARY public.test_stem
+alter text search dictionary test_stem (StopWords = dutch );
+NOTICE:  snitch: BEFORE any ALTER TEXT SEARCH DICTIONARY public.test_stem
+NOTICE:  snitch: AFTER any ALTER TEXT SEARCH DICTIONARY public.test_stem
 create text search parser test_parser (
   start = prsd_start,
   gettoken = prsd_nexttoken,
diff --git a/src/test/regress/sql/cmdtriggers.sql b/src/test/regress/sql/cmdtriggers.sql
index 82abb23..75bc573 100644
--- a/src/test/regress/sql/cmdtriggers.sql
+++ b/src/test/regress/sql/cmdtriggers.sql
@@ -218,6 +218,7 @@ create text search dictionary test_stem (
    template = snowball,
    language = 'english', stopwords = 'english'
 );
+alter text search dictionary test_stem (StopWords = dutch );
 
 create text search parser test_parser (
   start = prsd_start,
#16Thom Brown
thombrown@gmail.com
In reply to: Dimitri Fontaine (#15)
Re: Command Triggers, v16

On 16 March 2012 11:42, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Thom Brown <thombrown@gmail.com> writes:

Specific command triggers on ALTER VIEW don’t work at all:

Can't reproduce, and that's already part of the regression tests.

This was a problem my side (a mistake I made previously) as I hadn't
added this particular one into my list of created command triggers. I
had then seen the triggers fire, but forgot to go back and remove my
statement from the draft email. Apologies.

And I've been attaching an incremental patch too. Next patch revision is
expected later today with support for plpython, plperl and pltcl.

Okay, I shalln't do any more testing until the next patch. I should
probably have worked on automating my tests more, but never got round
to it.

Thom

#17Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Thom Brown (#16)
Re: Command Triggers, v16

Thom Brown <thombrown@gmail.com> writes:

Okay, I shalln't do any more testing until the next patch. I should
probably have worked on automating my tests more, but never got round
to it.

make installcheck :)

That said, your test allow to spot OID problems that we can't add in the
regression tests (OID being too volatile would break them), and I have
to look at how to add regression tests for the other pls support…

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#18Thom Brown
thombrown@gmail.com
In reply to: Dimitri Fontaine (#17)
Re: Command Triggers, v16

On 16 March 2012 12:07, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Thom Brown <thombrown@gmail.com> writes:

Okay, I shalln't do any more testing until the next patch.  I should
probably have worked on automating my tests more, but never got round
to it.

 make installcheck :)

That said, your test allow to spot OID problems that we can't add in the
regression tests (OID being too volatile would break them), and I have
to look at how to add regression tests for the other pls support…

Yes, that's why I don't use the regression tests. :)

Thom

#19Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andres Freund (#9)
Re: Command Triggers, v16

Andres Freund <andres@anarazel.de> writes:

On Thursday, March 15, 2012 10:58:49 PM Dimitri Fontaine wrote:

I tricked that in the grammar, the type is called cmdtrigger but I
though it wouldn't be a good choice for the SQL statement.

Hm. I am decidedly unhappy with that grammar hackery... But then maybe I am
squeamish.

Multi-word type names are a serious pain in the ass; they require
hackery in a lot of places. We support the ones that the SQL spec
requires us to, but I will object in the strongest terms to inventing
any that are not required by spec. I object in even stronger terms to
the incredibly klugy way you did it here.

If you think "cmdtrigger" isn't a good name maybe you should have
picked a different one to start with.

While I'm looking at the grammar ... it also seems like a serious
PITA from a maintenance standpoint that we're now going to have to
adjust the CREATE COMMAND TRIGGER productions every time somebody
thinks of a new SQL command. Maybe we should drop this whole idea
of specifying which commands a trigger acts on at the SQL level,
and just have one-size-fits-all command triggers. Or perhaps have
the selection be on the basis of strings that are matched to command
tags, instead of grammar constructs.

regards, tom lane

#20Andres Freund
andres@anarazel.de
In reply to: Tom Lane (#19)
Re: Command Triggers, v16

On Friday, March 16, 2012 02:50:55 PM Tom Lane wrote:

While I'm looking at the grammar ... it also seems like a serious
PITA from a maintenance standpoint that we're now going to have to
adjust the CREATE COMMAND TRIGGER productions every time somebody
thinks of a new SQL command.

I don't find that argument really convincing. The current state of the patch
will often require attention to command triggers anyway...

Andres

#21Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andres Freund (#20)
Re: Command Triggers, v16

Andres Freund <andres@anarazel.de> writes:

On Friday, March 16, 2012 02:50:55 PM Tom Lane wrote:

While I'm looking at the grammar ... it also seems like a serious
PITA from a maintenance standpoint that we're now going to have to
adjust the CREATE COMMAND TRIGGER productions every time somebody
thinks of a new SQL command.

I don't find that argument really convincing.

Well, how about just plain parser size bloat? Did anyone look at
how much bigger gram.o becomes with this? Bigger parser -> slower,
for everybody, whether they care about this feature or not.

regards, tom lane

#22Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#19)
Re: Command Triggers, v16

Tom Lane <tgl@sss.pgh.pa.us> writes:

Multi-word type names are a serious pain in the ass; they require
hackery in a lot of places. We support the ones that the SQL spec
requires us to, but I will object in the strongest terms to inventing
any that are not required by spec. I object in even stronger terms to
the incredibly klugy way you did it here.

Ok, it's so klugy that removing the support from the parser is going to
be easy.

If you think "cmdtrigger" isn't a good name maybe you should have
picked a different one to start with.

Well, I think it's a good internal name. I'm not too sure about exposing
it, the only reason why it's a good name is because it's a single not
too long word, after all. Not very “SQLish”.

I'm putting cmdtrigger as the user visible name in the next version of
the patch, if you come up with something potentially more user friendly
feel free to suggest.

While I'm looking at the grammar ... it also seems like a serious
PITA from a maintenance standpoint that we're now going to have to
adjust the CREATE COMMAND TRIGGER productions every time somebody
thinks of a new SQL command. Maybe we should drop this whole idea
of specifying which commands a trigger acts on at the SQL level,
and just have one-size-fits-all command triggers. Or perhaps have
the selection be on the basis of strings that are matched to command
tags, instead of grammar constructs.

The only advantage of doing it this way is giving the user an early
error when he's trying to attach to a non-supported command. I wouldn't
want to remove that list only to find myself adding a list of non
supported commands so that we can still refuse creating the useless
command trigger.

And as Andres said, adding command trigger support to a new command
isn't exactly transparent (it's still mostly mechanical though), so that
does not seems so big a pain to me. Of course I have been having my head
in there for a long time now…

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#23Robert Haas
robertmhaas@gmail.com
In reply to: Dimitri Fontaine (#15)
Re: Command Triggers, v16

On Fri, Mar 16, 2012 at 7:42 AM, Dimitri Fontaine
<dimitri@2ndquadrant.fr> wrote:

I don’t know if this was a problem before that I didn’t spot
(probably), but triggers for both ANY COMMAND and ALTER FOREIGN TABLE
show a command tag of ALTER TABLE for ALTER FOREIGN TABLE statements
where the column is renamed:

I don’t think this is the fault of the trigger code because it
actually says ALTER TABLE at the bottom, suggesting it’s something
already present.  This isn’t the case when adding or dropping columns.
 Any comments?

We're building command trigger on top of the existing code. From the
grammar we can see that an alter table and an alter foreign table are
processed as the same command.

This seems pretty dicey. I understand your position that it can't be
the job of the command triggers patch to fix every infelicity of the
backend, but on the flip side, code reuse is a good thing. We want to
increase, not decrease, the number of places where the same code can
be used to implement multiple commands that do related things; and
there has to be some way to do that without breaking command triggers.
Moreover, we really don't want the details of how things are handled
internally to be user-visible, because sometimes we refactor things to
improve the quality of our code, and I don't want to get bug reports
when we do that...

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#24Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Robert Haas (#23)
Re: Command Triggers, v16

Robert Haas <robertmhaas@gmail.com> writes:

there has to be some way to do that without breaking command triggers.

Sure, special case the switch branch in utility.c so as to return a
different command tag for ALTER TABLE and ALTER FOREIGN TABLE. For
precedents, see AlterObjectTypeCommandTag(ObjectType objtype) and

case T_DropStmt:
switch (((DropStmt *) parsetree)->removeType)

case T_DefineStmt:
switch (((DefineStmt *) parsetree)->kind)

So, do we want to do the same thing for ALTER FOREIGN TABLE, and should
I do that in the command triggers patch?

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#25Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#22)
Re: Command Triggers, v16

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

Tom Lane <tgl@sss.pgh.pa.us> writes:

If you think "cmdtrigger" isn't a good name maybe you should have
picked a different one to start with.

Well, I think it's a good internal name. I'm not too sure about exposing
it, the only reason why it's a good name is because it's a single not
too long word, after all. Not very “SQLish”.

I'm putting cmdtrigger as the user visible name in the next version of
the patch, if you come up with something potentially more user friendly
feel free to suggest.

How about "commandtrigger" or "command_trigger"? Typing a few more
characters in this context doesn't seem like a deal-breaker to me.

regards, tom lane

#26Thom Brown
thombrown@gmail.com
In reply to: Tom Lane (#25)
Re: Command Triggers, v16

On 16 March 2012 16:26, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

Tom Lane <tgl@sss.pgh.pa.us> writes:

If you think "cmdtrigger" isn't a good name maybe you should have
picked a different one to start with.

Well, I think it's a good internal name. I'm not too sure about exposing
it, the only reason why it's a good name is because it's a single not
too long word, after all. Not very “SQLish”.

I'm putting cmdtrigger as the user visible name in the next version of
the patch, if you come up with something potentially more user friendly
feel free to suggest.

How about "commandtrigger" or "command_trigger"?  Typing a few more
characters in this context doesn't seem like a deal-breaker to me.

+1

No objections to either of those suggestions, although I'd lean
towards the one without the underscore, not for any technical reason.
There is a precedent for a type with an underscore in its name
(txid_snapshot) but seems to be the exception.

Thom

#27Andres Freund
andres@2ndquadrant.com
In reply to: Dimitri Fontaine (#14)
Re: Command Triggers, v16

On Friday, March 16, 2012 10:40:46 AM Dimitri Fontaine wrote:

This will have the effect of calling triggers outside of alphabetic
order. I don't think thats a good idea even if one part is ANY and the
other a specific command.
I don't think there is any reason anymore to separate the two? The only

callsite seems to look like:

The idea is to have a predictable ordering of command triggers. The code
changed in the patch v16 (you pasted code from git in between v15 and
v16, I cleaned it up) and is now easier to read:

case CMD_TRIGGER_FIRED_BEFORE:
whenstr = "BEFORE";
procs[0] = cmd->before_any;
procs[1] = cmd->before;
break;

case CMD_TRIGGER_FIRED_AFTER:
whenstr = "AFTER";
procs[0] = cmd->after;
procs[1] = cmd->after_any;
break;

So it's BEFORE ANY then BEFORE command then AFTER command then AFTER
ANY. That's an arbitrary I made and we can easily reconsider. Triggers
are called in alphabetical order in each “slot” here.

In my mind it makes sense to have ANY triggers around the specific
triggers, but it's hard to explain why that feels better.

I still think this would be a mistake. I don't have a hard time imagining
usecases where a specific trigger should be called before or after an ANY
trigger because e.g. it wants to return a more specific error or doesn't want
to check all preconditions already done by the ANY trigger... All that would
be precluded by enforcing a strict ordering between ANY and specific triggers.
I don't see a use-case that would benefit from the current behaviour...

Andres
--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

#28Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#27)
Re: Command Triggers, v16

On Sun, Mar 25, 2012 at 12:15 PM, Andres Freund <andres@2ndquadrant.com> wrote:

On Friday, March 16, 2012 10:40:46 AM Dimitri Fontaine wrote:

This will have the effect of calling triggers outside of alphabetic
order. I don't think thats a good idea even if one part is ANY and the
other a specific command.
I don't think there is any reason anymore to separate the two? The only

callsite seems to look like:

The idea is to have a predictable ordering of command triggers. The code
changed in the patch v16 (you pasted code from git in between v15 and
v16, I cleaned it up) and is now easier to read:

                case CMD_TRIGGER_FIRED_BEFORE:
                        whenstr = "BEFORE";
                        procs[0] = cmd->before_any;
                        procs[1] = cmd->before;
                        break;

                case CMD_TRIGGER_FIRED_AFTER:
                        whenstr = "AFTER";
                        procs[0] = cmd->after;
                        procs[1] = cmd->after_any;
                        break;

So it's BEFORE ANY then BEFORE command then AFTER command then AFTER
ANY. That's an arbitrary I made and we can easily reconsider. Triggers
are called in alphabetical order in each “slot” here.

In my mind it makes sense to have ANY triggers around the specific
triggers, but it's hard to explain why that feels better.

I still think this would be a mistake. I don't have a hard time imagining
usecases where a specific trigger should be called before or after an ANY
trigger because e.g. it wants to return a more specific error or doesn't want
to check all preconditions already done by the ANY trigger... All that would
be precluded by enforcing a strict ordering between ANY and specific triggers.
I don't see a use-case that would benefit from the current behaviour...

Dimitri's proposed behavior would be advantageous if you have an ANY
trigger that wants to "take over the world" and make sure that nobody
else can run before it. I think, though, that's not a case we want to
cater to - all of this stuff requires superuser privileges anyway, so
we should assume that the DBA knows what he's doing. So +1 for making
it strictly alphabetical, as we do with other triggers. Everything
that can be done under Dimitri's proposal can also be done in that
scheme, but the reverse is not true.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#29Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Robert Haas (#28)
Re: Command Triggers, v16

Robert Haas <robertmhaas@gmail.com> writes:

Dimitri's proposed behavior would be advantageous if you have an ANY
trigger that wants to "take over the world" and make sure that nobody
else can run before it. I think, though, that's not a case we want to
cater to - all of this stuff requires superuser privileges anyway, so
we should assume that the DBA knows what he's doing. So +1 for making

What about extensions?

One use case would be for londiste/slony/bucardo to rewrite the command
and queue its text, that will be done in C and should probably be done
first. Using an ANY command trigger means that code will run before user
specific code (or likewise after it).

As I said it's not that clear in my head, but when thinking about
command trigger and extensions, it could be better to impose an
arbitrary order here.

it strictly alphabetical, as we do with other triggers. Everything
that can be done under Dimitri's proposal can also be done in that
scheme, but the reverse is not true.

That's true too. I'm just not sure how much it applies to code installed
by the DBA as opposed to written by the DBA. I'll be happy to edit the
patch to melt both lists if that's the decision, it's not hard to do so.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#30Thom Brown
thombrown@gmail.com
In reply to: Dimitri Fontaine (#29)
Re: Command Triggers, v16

Can someone clarify whether this will be reviewed by a committer?
Will there be time to get this reviewed before the commitfest closes?
I get the impression the commitfest closure is fairly imminent.

Thom

#31Robert Haas
robertmhaas@gmail.com
In reply to: Dimitri Fontaine (#29)
Re: Command Triggers, v16

On Mon, Mar 26, 2012 at 3:24 PM, Dimitri Fontaine
<dimitri@2ndquadrant.fr> wrote:

One use case would be for londiste/slony/bucardo to rewrite the command
and queue its text, that will be done in C and should probably be done
first. Using an ANY command trigger means that code will run before user
specific code (or likewise after it).

And, if the user wants it to be run first, he or she can do that. But
suppose he wants to run it first, and also forbid users whose username
starts with the letter b from running the ANALYZE command. Well,
then, he now wants that trigger to come before the other one, even
though the Slony trigger is for all commands (maybe) and the other
just for ANALYZE (maybe).

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#32Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#29)
Re: Command Triggers, v16

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

Robert Haas <robertmhaas@gmail.com> writes:

Dimitri's proposed behavior would be advantageous if you have an ANY
trigger that wants to "take over the world" and make sure that nobody
else can run before it. I think, though, that's not a case we want to
cater to - all of this stuff requires superuser privileges anyway, so
we should assume that the DBA knows what he's doing. So +1 for making

What about extensions?

One use case would be for londiste/slony/bucardo to rewrite the command
and queue its text, that will be done in C and should probably be done
first. Using an ANY command trigger means that code will run before user
specific code (or likewise after it).

Unless you intend a restriction that there be only one ANY trigger,
I don't see how that follows. AFAICS, the only way to guarantee "my
trigger runs first" is to give it a name alphabetically before anything
else in the system.

Also, it strikes me that in most of the trigger ordering cases I've
seen, it's actually more interesting to want to be sure that a
particular trigger runs *last* so that its effects can't be modified
by some other, hypothetically less trusted, trigger.

So I don't think that the mere fact of being an ANY trigger rather than
a command-specific trigger should be taken to mean that a particular
ordering is desirable. Trigger name order isn't the greatest solution
by any means, but it's more flexible than hard-wiring according to
trigger type.

regards, tom lane

#33Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thom Brown (#30)
Re: Command Triggers, v16

Thom Brown <thombrown@gmail.com> writes:

Can someone clarify whether this will be reviewed by a committer?
Will there be time to get this reviewed before the commitfest closes?
I get the impression the commitfest closure is fairly imminent.

I don't have that impression. (I wish I did.)

regards, tom lane

#34Robert Haas
robertmhaas@gmail.com
In reply to: Thom Brown (#30)
Re: Command Triggers, v16

On Mon, Mar 26, 2012 at 3:36 PM, Thom Brown <thombrown@gmail.com> wrote:

Can someone clarify whether this will be reviewed by a committer?
Will there be time to get this reviewed before the commitfest closes?
I get the impression the commitfest closure is fairly imminent.

Well, I have been holding off for two reasons:

1. It sure seems like there is an awful lot of code churn and design
work going on.

2. I'm not sure which patches Tom is planning to look at or in what
order, so I've been avoiding the ones he seems to be taking an
interest in.

Personally, I am about at the point where I'd like to punt everything
and move on. As nice as it would be to squeeze a few more things into
9.2, there WILL be a 9.3. If a few less people had submitted
half-baked code at the last minute and a few more people had helped
with review, we'd be done by now.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#35Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#32)
Re: Command Triggers, v16

Tom Lane <tgl@sss.pgh.pa.us> writes:

So I don't think that the mere fact of being an ANY trigger rather than
a command-specific trigger should be taken to mean that a particular
ordering is desirable. Trigger name order isn't the greatest solution
by any means, but it's more flexible than hard-wiring according to
trigger type.

That ANY sandwich idea is then dead, I will fix it tomorrow to rather
just handle a single list of BEFORE and AFTER triggers (that's 2 lists
total) ordered by trigger name.

v19 will also integrate latest doc comments from Thom and most from
Andres, I don't know how to fix the plpython specifics he's talking
about.

About the reviewing and the commit fest closing, even if that patch is
big it's a principled implementation: the integration of the facility is
done in the same way in lots of different places, and is not rocket
science either (we removed all the complexity). So I guess it's not
really an herculean job here, just a certain amount of mechanical edits:
we just support too many commands ;)

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#36Andres Freund
andres@2ndquadrant.com
In reply to: Dimitri Fontaine (#35)
Re: Command Triggers, v16

On Monday, March 26, 2012 10:18:59 PM Dimitri Fontaine wrote:

don't know how to fix the plpython specifics he's talking
about.

Just copy what is done in the normal trigger handling facility (the decref
both in the CATCH and in the normal path). Ping me some other way if you need
help...

Andres
--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

#37Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Robert Haas (#34)
Re: Command Triggers, v16

Robert Haas <robertmhaas@gmail.com> writes:

1. It sure seems like there is an awful lot of code churn and design
work going on.

There has only been minor adjustments for a while now, and they have
been visible because Thom was doing lots of testing for me and it was
way easier for me to publish a new version and have a test result the
next day (thanks again Thom).

Personally, I am about at the point where I'd like to punt everything
and move on. As nice as it would be to squeeze a few more things into
9.2, there WILL be a 9.3. If a few less people had submitted
half-baked code at the last minute and a few more people had helped
with review, we'd be done by now.

Well, wait a minute. There's a difference between half-baked and
reacting to a review that changes the goal of a patch. My idea of the
code I wanted to write here is extremely different from what we as a
community decided to be doing. The main part of the code churn has been
answering to review, removing features and cleaning the code afterwards.

The only major design decision that I had to change here has been about
from where to call in the command trigger code in the existing commands
implementation, and it was done before entering this CF, IIRC.

If you want to punt this patch out of 9.2 after all the changes I had to
make for it to be a candidate for 9.2, I think it would be only fair for
you to find a show stopper in my current implementation. The trigger
firing order is about an hour of work, so not a stopper I believe.

And as soon as we're done here, you know I'll put the same hours and
energy into reviewing other people patches :)

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#38Thom Brown
thombrown@gmail.com
In reply to: Dimitri Fontaine (#37)
Re: Command Triggers, v16

On 26 March 2012 21:36, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Robert Haas <robertmhaas@gmail.com> writes:

Personally, I am about at the point where I'd like to punt everything
and move on.  As nice as it would be to squeeze a few more things into
9.2, there WILL be a 9.3.  If a few less people had submitted
half-baked code at the last minute and a few more people had helped
with review, we'd be done by now.

Well, wait a minute. There's a difference between half-baked and
reacting to a review that changes the goal of a patch. My idea of the

I think Robert was referring to patches in general.

Thom

#39Robert Haas
robertmhaas@gmail.com
In reply to: Dimitri Fontaine (#37)
Re: Command Triggers, v16

On Mon, Mar 26, 2012 at 4:36 PM, Dimitri Fontaine
<dimitri@2ndquadrant.fr> wrote:

Well, wait a minute. There's a difference between half-baked and
reacting to a review that changes the goal of a patch. My idea of the
code I wanted to write here is extremely different from what we as a
community decided to be doing. The main part of the code churn has been
answering to review, removing features and cleaning the code afterwards.

Sure. And if this weren't the final CommitFest, we would have bumped
this to the next CommitFest two months ago. Since it is the final
CommitFest, we're going to go on and on and on. Already we have
almost as many patches queued up for the next CommitFest as we do
remaining in this one. So my question is: how long should we keep all
those people waiting for the purpose of squeezing more stuff into 9.2?
At the beginning of this CommitFest, various people offered time
frames ranging between 6 weeks to 2 months. We're past that now. If
you don't think that was a long enough time frame, then how long do
you think we should wait? It doesn't seem to me to matter very much
whether this got stretched out due to fundamental design deficiencies
or just because it takes a while to beat a major feature into
committable form; surely it's not a shock that this patch wasn't going
to go in overnight.

If you want to punt this patch out of 9.2 after all the changes I had to
make for it to be a candidate for 9.2, I think it would be only fair for
you to find a show stopper in my current implementation. The trigger
firing order is about an hour of work, so not a stopper I believe.

I don't think there is a show-stopper. I do think there is probably a
lot more cleaning up, tidying, and adjusting needed.

And as soon as we're done here, you know I'll put the same hours and
energy into reviewing other people patches :)

As soon as we're done here, the CommitFest will end, and there won't
be any other people's patches to review.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#40Christopher Browne
cbbrowne@gmail.com
In reply to: Robert Haas (#39)
Re: Command Triggers, v16

On Mon, Mar 26, 2012 at 4:45 PM, Robert Haas <robertmhaas@gmail.com> wrote:

As soon as we're done here, the CommitFest will end, and there won't
be any other people's patches to review.

Hurray? :-)
--
When confronted by a difficult problem, solve it by reducing it to the
question, "How would the Lone Ranger handle this?"

#41Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#34)
Re: Command Triggers, v16

Robert Haas <robertmhaas@gmail.com> writes:

2. I'm not sure which patches Tom is planning to look at or in what
order, so I've been avoiding the ones he seems to be taking an
interest in.

Well, I think I'm definitely on the hook for the pg_stat_statements,
pgsql_fdw, foreign table stats, and caching-stable-subexpressions
patches, and I should look at the libpq alternate row returning
mechanism because I suspect I was the last one to mess with that libpq
code in any detail. I don't claim any special insight into the other
stuff on the list. In particular I've not been paying much attention
to command triggers.

Personally, I am about at the point where I'd like to punt everything
and move on. As nice as it would be to squeeze a few more things into
9.2, there WILL be a 9.3. If a few less people had submitted
half-baked code at the last minute and a few more people had helped
with review, we'd be done by now.

The main reason I proposed setting a schedule a few weeks ago was that
I was afraid the commitfest would otherwise end precisely in a "we're
tired out, we're punting everything to 9.3" moment. Without some
definite goal to work towards, it'll just keep stretching out until
we've had enough. I'd prefer it end in a more orderly fashion than
that. The end result will be the same, in the sense that some of the
stuff that's still-not-ready-for-committer is going to get punted,
but people might have a less bad taste in their mouths about why.

regards, tom lane

#42Robert Haas
robertmhaas@gmail.com
In reply to: Tom Lane (#41)
Re: Command Triggers, v16

On Mar 26, 2012, at 5:36 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Robert Haas <robertmhaas@gmail.com> writes:

2. I'm not sure which patches Tom is planning to look at or in what
order, so I've been avoiding the ones he seems to be taking an
interest in.

Well, I think I'm definitely on the hook for the pg_stat_statements,
pgsql_fdw, foreign table stats, and caching-stable-subexpressions
patches, and I should look at the libpq alternate row returning
mechanism because I suspect I was the last one to mess with that libpq
code in any detail. I don't claim any special insight into the other
stuff on the list. In particular I've not been paying much attention
to command triggers.

How long will that all take?

I guess I'll work on command triggers, pg_archivecleanup, and buffer I/O timings next.

Personally, I am about at the point where I'd like to punt everything
and move on. As nice as it would be to squeeze a few more things into
9.2, there WILL be a 9.3. If a few less people had submitted
half-baked code at the last minute and a few more people had helped
with review, we'd be done by now.

The main reason I proposed setting a schedule a few weeks ago was that
I was afraid the commitfest would otherwise end precisely in a "we're
tired out, we're punting everything to 9.3" moment. Without some
definite goal to work towards, it'll just keep stretching out until
we've had enough. I'd prefer it end in a more orderly fashion than
that. The end result will be the same, in the sense that some of the
stuff that's still-not-ready-for-committer is going to get punted,
but people might have a less bad taste in their mouths about why.

Fine. What do you propose, specifically?

...Robert

#43Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#42)
Re: 9.2 commitfest closure (was Command Triggers, v16)

Robert Haas <robertmhaas@gmail.com> writes:

On Mar 26, 2012, at 5:36 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Robert Haas <robertmhaas@gmail.com> writes:

2. I'm not sure which patches Tom is planning to look at or in what
order, so I've been avoiding the ones he seems to be taking an
interest in.

Well, I think I'm definitely on the hook for the pg_stat_statements,
pgsql_fdw, foreign table stats, and caching-stable-subexpressions
patches, and I should look at the libpq alternate row returning
mechanism because I suspect I was the last one to mess with that libpq
code in any detail.

How long will that all take?

Dunno, but surely at least a day apiece if they're to be pushed to
commit. On the other hand, considering that none of them is actually
Ready For Committer right now, we possibly shouldn't expect that they'll
all get committed.

Personally, I am about at the point where I'd like to punt everything
and move on. As nice as it would be to squeeze a few more things into
9.2, there WILL be a 9.3. If a few less people had submitted
half-baked code at the last minute and a few more people had helped
with review, we'd be done by now.

The main reason I proposed setting a schedule a few weeks ago was that
I was afraid the commitfest would otherwise end precisely in a "we're
tired out, we're punting everything to 9.3" moment. Without some
definite goal to work towards, it'll just keep stretching out until
we've had enough. I'd prefer it end in a more orderly fashion than
that. The end result will be the same, in the sense that some of the
stuff that's still-not-ready-for-committer is going to get punted,
but people might have a less bad taste in their mouths about why.

Fine. What do you propose, specifically?

The end of the month is coming up. How about we propose to close the
'fest on April 1st? Anything that's not committable by then goes to
the 9.3 list. If one week seems too short, how about 2 weeks?

Thom Brown <thom@linux.com> writes:

This is probably a dumb question but... surely there's more than 2
committers able to review?

Able and willing might be two different things. Alvaro, Heikki, and
Magnus have all been looking at stuff, but I think they may be getting
burned out too.

regards, tom lane

#44Magnus Hagander
magnus@hagander.net
In reply to: Tom Lane (#43)
Re: 9.2 commitfest closure (was Command Triggers, v16)

On Tue, Mar 27, 2012 at 01:39, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Robert Haas <robertmhaas@gmail.com> writes:
Thom Brown <thom@linux.com> writes:

This is probably a dumb question but... surely there's more than 2
committers able to review?

Able and willing might be two different things.  Alvaro, Heikki, and
Magnus have all been looking at stuff, but I think they may be getting
burned out too.

Can't honestly claim I've been burned out by it - more that I feel bad
fo rnot having "done my part" :-O

It's not the CF itself, but a whole lot of other things (non-postgres)
that have been taking my time.

I'll try to get my head around the pg_stat_bgwriter patch - which I
htink actually has the wrong status on the CF page after talking to
Greg about it tonight.

--
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/

#45Simon Riggs
simon@2ndQuadrant.com
In reply to: Tom Lane (#43)
Re: 9.2 commitfest closure (was Command Triggers, v16)

On Tue, Mar 27, 2012 at 12:39 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thom Brown <thom@linux.com> writes:

This is probably a dumb question but... surely there's more than 2
committers able to review?

Able and willing might be two different things.  Alvaro, Heikki, and
Magnus have all been looking at stuff, but I think they may be getting
burned out too.

If people are keeping score, add myself and Robert also, maybe others
- I've not been watching too closely.

On average there appears to be about 10 patches per active committer
in this CF. Given the complexity of the patches in last CF always
seems to be higher, that is a huge number and represents weeks of
work.

One of the key problems I see is that few people actually get paid to
do this, so its fairly hard to allocate time. I want to make it a
policy of "1 for 1" so if you write a patch you need to review a
patch. That way sponsors are forced to spend money on review time for
stuff they may not care about as a trade for getting reviews on stuff
they do. This would take pressure off the few.

--
 Simon Riggs                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services

#46Robert Haas
robertmhaas@gmail.com
In reply to: Tom Lane (#43)
Re: 9.2 commitfest closure (was Command Triggers, v16)

On Mon, Mar 26, 2012 at 7:39 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Fine. What do you propose, specifically?

The end of the month is coming up.  How about we propose to close the
'fest on April 1st?  Anything that's not committable by then goes to
the 9.3 list.  If one week seems too short, how about 2 weeks?

Let's split the difference: how about we close it a week from this
Friday. That would be April 6, 2012, ten days from today.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#47Robert Haas
robertmhaas@gmail.com
In reply to: Robert Haas (#46)
Re: 9.2 commitfest closure (was Command Triggers, v16)

On Tue, Mar 27, 2012 at 1:36 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Mon, Mar 26, 2012 at 7:39 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Fine. What do you propose, specifically?

The end of the month is coming up.  How about we propose to close the
'fest on April 1st?  Anything that's not committable by then goes to
the 9.3 list.  If one week seems too short, how about 2 weeks?

Let's split the difference: how about we close it a week from this
Friday.  That would be April 6, 2012, ten days from today.

Anybody, anybody? Can we try to get some agreement on this?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#48Simon Riggs
simon@2ndQuadrant.com
In reply to: Robert Haas (#47)
Re: 9.2 commitfest closure (was Command Triggers, v16)

On Wed, Mar 28, 2012 at 2:45 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Tue, Mar 27, 2012 at 1:36 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Mon, Mar 26, 2012 at 7:39 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Fine. What do you propose, specifically?

The end of the month is coming up.  How about we propose to close the
'fest on April 1st?  Anything that's not committable by then goes to
the 9.3 list.  If one week seems too short, how about 2 weeks?

Let's split the difference: how about we close it a week from this
Friday.  That would be April 6, 2012, ten days from today.

Anybody, anybody?  Can we try to get some agreement on this?

I agree.

I have a few projects still on the table myself, but my main concern
is Alvaro's FK locks patch. Depending on how the bones lie I will
finish up some combination of those by end of next week.

--
 Simon Riggs                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services

#49Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#47)
Re: 9.2 commitfest closure (was Command Triggers, v16)

Robert Haas <robertmhaas@gmail.com> writes:

On Tue, Mar 27, 2012 at 1:36 PM, Robert Haas <robertmhaas@gmail.com> wrote:

Let's split the difference: how about we close it a week from this
Friday. That would be April 6, 2012, ten days from today.

Anybody, anybody? Can we try to get some agreement on this?

Works for me.

regards, tom lane

#50Noah Misch
noah@leadboat.com
In reply to: Robert Haas (#47)
Re: 9.2 commitfest closure (was Command Triggers, v16)

On Wed, Mar 28, 2012 at 09:45:29AM -0400, Robert Haas wrote:

On Tue, Mar 27, 2012 at 1:36 PM, Robert Haas <robertmhaas@gmail.com> wrote:

Let's split the difference: how about we close it a week from this
Friday. ?That would be April 6, 2012, ten days from today.

Anybody, anybody? Can we try to get some agreement on this?

+1