Thread

  1. not null validation option in contrib/file_fdw

    Etsuro Fujita <fujita.etsuro@lab.ntt.co.jp> — 2012-04-13T07:59:23Z

    I updated the patch added to CF 2012-Next [1].  Attached is the updated
    version of the patch.
    
    For the discussion in [2], I've introduced a new generic option, validate
    for file_fdw foreign tables, which specifies if file_fdw verifies that
    tuples meet NOT NULL constraints.  The default value for the option is
    'false', and if the value is set to 'true', then file_fdw verifies NOT NULL
    constraints.  For example, a user can issue the following to let file_fdw
    verify the constraint of the msg column.
    
        CREATE FOREIGN TABLE ft (id INTEGER, msg TEXT NOT NULL)
                      SERVER fs
                     OPTIONS (filename '/path/to/file', format 'csv',
                              delimiter ',', validate 'true');
    
    At the SELECT time, ABORT is issued when a NOT NULL violation error has been
    found, like COPY FROM.  Once the validation is done successfully using e.g.
    SELECT COUNT(*), the user can set the option to 'false' using ALTER FOREIGN
    TABLE.  I think this option is needed for flat files due to their lack of
    ability to check such a constraint.
    
    (I added NOT NULL checking to ileIterateForeignScan(), but not to
    file_acquire_sample_rows().  Should we do that at
    file_acquire_sample_rows()?  I think it is good to just recommend that users
    do ANALYZE a foreign table after the validation.)
    
    For the discussion in [3], I've added a new external function
    ExecNotNullCheck() and call it from fileIterateForeignScan.
    
    Any comments are welcome.
    
    Best regards,
    Etsuro Fujita
    
    [1] https://commitfest.postgresql.org/action/patch_view?id=822
    [2] http://archives.postgresql.org/message-id/1038.1331738954@sss.pgh.pa.us
    [3] http://archives.postgresql.org/pgsql-hackers/2012-03/msg00809.php
    
    
  2. Re: not null validation option in contrib/file_fdw

    Shigeru Hanada <shigeru.hanada@gmail.com> — 2012-04-13T11:21:52Z

    (2012/04/13 16:59), Etsuro Fujita wrote:
    > I updated the patch added to CF 2012-Next [1].  Attached is the updated
    > version of the patch.
    
    I applied the patch and ran regression tests of file_fdw, and I got
    SIGSEGV X-(
    
    The failure occurs in fileGetOptions, and it is caused by
    list_delete_cell used in foreach loop; ListCell points delete target has
    been free-ed in list_delete_cell, but foreach accesses it to get next
    element.
    
    Some of backend functions which use list_delete_cell in loop use "for"
    loop instead of foreach, and other functions exit the loop after calling
    list_delete_cell.  Since we can't stop searching non-COPY options until
    meeting the end of the options list, we would need to choose former
    ("for" loop), or create another list which contains only valid COPY
    options and return it via other_options parameter.
    
    Regards,
    -- 
    Shigeru HANADA
    
    
  3. Re: not null validation option in contrib/file_fdw

    Andrew Dunstan <andrew@dunslane.net> — 2012-04-13T12:16:18Z

    
    On 04/13/2012 07:21 AM, Shigeru HANADA wrote:
    > (2012/04/13 16:59), Etsuro Fujita wrote:
    >> I updated the patch added to CF 2012-Next [1].  Attached is the updated
    >> version of the patch.
    > I applied the patch and ran regression tests of file_fdw, and I got
    > SIGSEGV X-(
    >
    > The failure occurs in fileGetOptions, and it is caused by
    > list_delete_cell used in foreach loop; ListCell points delete target has
    > been free-ed in list_delete_cell, but foreach accesses it to get next
    > element.
    >
    > Some of backend functions which use list_delete_cell in loop use "for"
    > loop instead of foreach, and other functions exit the loop after calling
    > list_delete_cell.  Since we can't stop searching non-COPY options until
    > meeting the end of the options list, we would need to choose former
    > ("for" loop), or create another list which contains only valid COPY
    > options and return it via other_options parameter.
    >
    
    Yes, the code in fileGetOptions() appears to be bogus.
    
    Also, "validate" is a terrible name for the option (and in the code)
    IMNSHO. It's far too generic. "validate_not_null" or some such would
    surely be better.
    
    cheers
    
    andrew
    
    
    
  4. Re: not null validation option in contrib/file_fdw

    Etsuro Fujita <fujita.etsuro@lab.ntt.co.jp> — 2012-04-16T07:08:44Z

    Thank you for the review.
    
    > -----Original Message-----
    > From: pgsql-hackers-owner@postgresql.org
    > [mailto:pgsql-hackers-owner@postgresql.org] On Behalf Of Andrew Dunstan
    > Sent: Friday, April 13, 2012 9:16 PM
    > To: Shigeru HANADA
    > Cc: Etsuro Fujita; pgsql-hackers@postgresql.org
    > Subject: Re: [HACKERS] not null validation option in contrib/file_fdw
    > 
    > 
    > 
    > On 04/13/2012 07:21 AM, Shigeru HANADA wrote:
    > > (2012/04/13 16:59), Etsuro Fujita wrote:
    > >> I updated the patch added to CF 2012-Next [1].  Attached is the
    > >> updated version of the patch.
    > > I applied the patch and ran regression tests of file_fdw, and I got
    > > SIGSEGV X-(
    > >
    > > The failure occurs in fileGetOptions, and it is caused by
    > > list_delete_cell used in foreach loop; ListCell points delete target
    > > has been free-ed in list_delete_cell, but foreach accesses it to get
    > > next element.
    > >
    > > Some of backend functions which use list_delete_cell in loop use "for"
    > > loop instead of foreach, and other functions exit the loop after
    > > calling list_delete_cell.  Since we can't stop searching non-COPY
    > > options until meeting the end of the options list, we would need to
    > > choose former ("for" loop), or create another list which contains only
    > > valid COPY options and return it via other_options parameter.
    > >
    > 
    > Yes, the code in fileGetOptions() appears to be bogus.
    
    Sorry, I will fix it.
    
    > Also, "validate" is a terrible name for the option (and in the code)
    IMNSHO.
    > It's far too generic. "validate_not_null" or some such would surely be
    > better.
    
    I thought it would be used for not only NOT NULL but also CHECK and foreign
    key constraints.  That is, when a user sets the option to 'true', file_fdw
    verifies that each tuple meets all kinds of constraints.  So, how about
    "validate_data_file" or simply "validate_file"?
    
    Best regards,
    Etsuro Fujita
    
    > cheers
    > 
    > andrew
    > 
    > 
    > --
    > Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make
    > changes to your subscription:
    > http://www.postgresql.org/mailpref/pgsql-hackers
    
    
    
    
  5. Re: not null validation option in contrib/file_fdw

    Etsuro Fujita <fujita.etsuro@lab.ntt.co.jp> — 2012-04-17T05:39:31Z

    I updated the patch.  Attached is an updated version of the patch.
    
    Changes:
      * fix a bug in fileGetOptions()
      * rename the validation option and its code to "validate_data_file"
      * clean up
    
    Best regards,
    Etsuro Fujita
    
    > -----Original Message-----
    > From: pgsql-hackers-owner@postgresql.org
    > [mailto:pgsql-hackers-owner@postgresql.org] On Behalf Of Etsuro Fujita
    > Sent: Monday, April 16, 2012 4:09 PM
    > To: 'Andrew Dunstan'; 'Shigeru HANADA'
    > Cc: pgsql-hackers@postgresql.org
    > Subject: Re: [HACKERS] not null validation option in contrib/file_fdw
    > 
    > Thank you for the review.
    > 
    > > -----Original Message-----
    > > From: pgsql-hackers-owner@postgresql.org
    > > [mailto:pgsql-hackers-owner@postgresql.org] On Behalf Of Andrew
    > > Dunstan
    > > Sent: Friday, April 13, 2012 9:16 PM
    > > To: Shigeru HANADA
    > > Cc: Etsuro Fujita; pgsql-hackers@postgresql.org
    > > Subject: Re: [HACKERS] not null validation option in contrib/file_fdw
    > >
    > >
    > >
    > > On 04/13/2012 07:21 AM, Shigeru HANADA wrote:
    > > > (2012/04/13 16:59), Etsuro Fujita wrote:
    > > >> I updated the patch added to CF 2012-Next [1].  Attached is the
    > > >> updated version of the patch.
    > > > I applied the patch and ran regression tests of file_fdw, and I got
    > > > SIGSEGV X-(
    > > >
    > > > The failure occurs in fileGetOptions, and it is caused by
    > > > list_delete_cell used in foreach loop; ListCell points delete target
    > > > has been free-ed in list_delete_cell, but foreach accesses it to get
    > > > next element.
    > > >
    > > > Some of backend functions which use list_delete_cell in loop use "for"
    > > > loop instead of foreach, and other functions exit the loop after
    > > > calling list_delete_cell.  Since we can't stop searching non-COPY
    > > > options until meeting the end of the options list, we would need to
    > > > choose former ("for" loop), or create another list which contains
    > > > only valid COPY options and return it via other_options parameter.
    > > >
    > >
    > > Yes, the code in fileGetOptions() appears to be bogus.
    > 
    > Sorry, I will fix it.
    > 
    > > Also, "validate" is a terrible name for the option (and in the code)
    > IMNSHO.
    > > It's far too generic. "validate_not_null" or some such would surely be
    > > better.
    > 
    > I thought it would be used for not only NOT NULL but also CHECK and
    foreign
    > key constraints.  That is, when a user sets the option to 'true', file_fdw
    > verifies that each tuple meets all kinds of constraints.  So, how about
    > "validate_data_file" or simply "validate_file"?
    > 
    > Best regards,
    > Etsuro Fujita
    > 
    > > cheers
    > >
    > > andrew
    > >
    > >
    > > --
    > > Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To
    > > make changes to your subscription:
    > > http://www.postgresql.org/mailpref/pgsql-hackers
    > 
    > 
    > 
    > --
    > Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make
    > changes to your subscription:
    > http://www.postgresql.org/mailpref/pgsql-hackers
    
    
  6. Re: not null validation option in contrib/file_fdw

    Etsuro Fujita <fujita.etsuro@lab.ntt.co.jp> — 2012-06-21T11:20:56Z

    I rebased the patch to current head.  Attached is an updated version of the
    patch.
    
    Best regards,
    Etsuro Fujita
    
    > -----Original Message-----
    > From: pgsql-hackers-owner@postgresql.org
    > [mailto:pgsql-hackers-owner@postgresql.org] On Behalf Of Etsuro Fujita
    > Sent: Tuesday, April 17, 2012 2:40 PM
    > To: 'Andrew Dunstan'; 'Shigeru HANADA'
    > Cc: pgsql-hackers@postgresql.org
    > Subject: Re: [HACKERS] not null validation option in contrib/file_fdw
    >
    > I updated the patch.  Attached is an updated version of the patch.
    >
    > Changes:
    >   * fix a bug in fileGetOptions()
    >   * rename the validation option and its code to "validate_data_file"
    >   * clean up
    >
    > Best regards,
    > Etsuro Fujita
    >
    > > -----Original Message-----
    > > From: pgsql-hackers-owner@postgresql.org
    > > [mailto:pgsql-hackers-owner@postgresql.org] On Behalf Of Etsuro Fujita
    > > Sent: Monday, April 16, 2012 4:09 PM
    > > To: 'Andrew Dunstan'; 'Shigeru HANADA'
    > > Cc: pgsql-hackers@postgresql.org
    > > Subject: Re: [HACKERS] not null validation option in contrib/file_fdw
    > >
    > > Thank you for the review.
    > >
    > > > -----Original Message-----
    > > > From: pgsql-hackers-owner@postgresql.org
    > > > [mailto:pgsql-hackers-owner@postgresql.org] On Behalf Of Andrew
    > > > Dunstan
    > > > Sent: Friday, April 13, 2012 9:16 PM
    > > > To: Shigeru HANADA
    > > > Cc: Etsuro Fujita; pgsql-hackers@postgresql.org
    > > > Subject: Re: [HACKERS] not null validation option in
    > > > contrib/file_fdw
    > > >
    > > >
    > > >
    > > > On 04/13/2012 07:21 AM, Shigeru HANADA wrote:
    > > > > (2012/04/13 16:59), Etsuro Fujita wrote:
    > > > >> I updated the patch added to CF 2012-Next [1].  Attached is the
    > > > >> updated version of the patch.
    > > > > I applied the patch and ran regression tests of file_fdw, and I
    > > > > got SIGSEGV X-(
    > > > >
    > > > > The failure occurs in fileGetOptions, and it is caused by
    > > > > list_delete_cell used in foreach loop; ListCell points delete
    > > > > target has been free-ed in list_delete_cell, but foreach accesses
    > > > > it to get next element.
    > > > >
    > > > > Some of backend functions which use list_delete_cell in loop use
    "for"
    > > > > loop instead of foreach, and other functions exit the loop after
    > > > > calling list_delete_cell.  Since we can't stop searching non-COPY
    > > > > options until meeting the end of the options list, we would need
    > > > > to choose former ("for" loop), or create another list which
    > > > > contains only valid COPY options and return it via other_options
    > parameter.
    > > > >
    > > >
    > > > Yes, the code in fileGetOptions() appears to be bogus.
    > >
    > > Sorry, I will fix it.
    > >
    > > > Also, "validate" is a terrible name for the option (and in the code)
    > > IMNSHO.
    > > > It's far too generic. "validate_not_null" or some such would surely
    > > > be better.
    > >
    > > I thought it would be used for not only NOT NULL but also CHECK and
    > foreign
    > > key constraints.  That is, when a user sets the option to 'true',
    > > file_fdw verifies that each tuple meets all kinds of constraints.  So,
    > > how about "validate_data_file" or simply "validate_file"?
    > >
    > > Best regards,
    > > Etsuro Fujita
    > >
    > > > cheers
    > > >
    > > > andrew
    > > >
    > > >
    > > > --
    > > > Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
    > > > To make changes to your subscription:
    > > > http://www.postgresql.org/mailpref/pgsql-hackers
    > >
    > >
    > >
    > > --
    > > Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To
    > > make changes to your subscription:
    > > http://www.postgresql.org/mailpref/pgsql-hackers
    
    
    
    begin 666 file_fdw_notnull_v4.patch
    M9&EF9B M+6=I="!A+V-O;G1R:6(O9FEL95]F9'<O9FEL95]F9'<N8R!B+V-O
    M;G1R:6(O9FEL95]F9'<O9FEL95]F9'<N8PII;F1E>"!E,V(Y,C(S+BXQ.3$X
    M-6(X(#$P,#8T- HM+2T@82]C;VYT<FEB+V9I;&5?9F1W+V9I;&5?9F1W+F,*
    M*RLK(&(O8V]N=')I8B]F:6QE7V9D=R]F:6QE7V9D=RYC"D! ("TW,2PV("LW
    M,2PY($! ('-T871I8R!C;VYS="!S=')U8W0@1FEL949D=T]P=&EO;B!V86QI
    M9%]O<'1I;VYS6UT@/2!["B )("H@9F]R8V5?<75O=&4@:7,@;F]T('-U<'!O
    M<G1E9"!B>2!F:6QE7V9D=R!B96-A=7-E(&ET)W,@9F]R($-/4%D@5$\N"B )
    M("HO"B **PDO*B!686QI9&%T:6]N(&]P=&EO;G,@*B\**PE[(G9A;&ED871E
    M7V1A=&%?9FEL92(L($9O<F5I9VY486)L95)E;&%T:6]N261]+ HK"B )+RH@
    M4V5N=&EN96P@*B\*( E[3E5,3"P@26YV86QI9$]I9'T*('T["D! ("TY-"PV
    M("LY-RPX($! ('1Y<&5D968@<W1R=6-T($9I;&5&9'=%>&5C=71I;VY3=&%T
    M90H@"6-H87()(" @*F9I;&5N86UE.PD)+RH@9FEL92!T;R!R96%D("HO"B )
    M3&ES= D@(" J;W!T:6]N<SL)"2\J(&UE<F=E9"!#3U!9(&]P=&EO;G,L(&5X
    M8VQU9&EN9R!F:6QE;F%M92 J+PH@"4-O<'E3=&%T90EC<W1A=&4["0D)+RH@
    M<W1A=&4@;V8@<F5A9&EN9R!F:6QE("HO"BL)8F]O; D)=F%L:61A=&5?9&%T
    M85]F:6QE.PHK"0D)"0D)"0DO*B!W:&5T:&5R('1O('9A;&ED871E($Y/5"!.
    M54Q,(&-O;G-T<F%I;G1S("HO"B!]($9I;&5&9'=%>&5C=71I;VY3=&%T93L*
    M( H@+RH*0$ @+3$S-"PW("LQ,SDL.2! 0"!S=&%T:6,@8F]O;"!F:6QE06YA
    M;'EZ949O<F5I9VY486)L92A296QA=&EO;B!R96QA=&EO;BP*(" J+PH@<W1A
    M=&EC(&)O;VP@:7-?=F%L:61?;W!T:6]N*&-O;G-T(&-H87(@*F]P=&EO;BP@
    M3VED(&-O;G1E>'0I.PH@<W1A=&EC('9O:60@9FEL94=E=$]P=&EO;G,H3VED
    M(&9O<F5I9VYT86)L96ED+ HM"0D)(" @8VAA<B J*F9I;&5N86UE+"!,:7-T
    M("HJ;W1H97)?;W!T:6]N<RD["BL)"0D)"0D@("!C:&%R("HJ9FEL96YA;64L
    M"BL)"0D)"0D@("!,:7-T("HJ;W1H97)?;W!T:6]N<RP**PD)"0D)"2 @(&)O
    M;VP@*G9A;&ED871E7V1A=&%?9FEL92D["B!S=&%T:6,@3&ES=" J9V5T7V9I
    M;&5?9F1W7V%T=')I8G5T95]O<'1I;VYS*$]I9"!R96QI9"D["B!S=&%T:6,@
    M=F]I9"!E<W1I;6%T95]S:7IE*%!L86YN97));F9O("IR;V]T+"!296Q/<'1)
    M;F9O("IB87-E<F5L+ H@"0D)("!&:6QE1F1W4&QA;E-T871E("IF9'=?<')I
    M=F%T92D["D! ("TQ.#(L-B K,3@Y+#<@0$ @9FEL95]F9'=?=F%L:61A=&]R
    M*%!'7T953D-424].7T%21U,I"B )8VAA<@D@(" J9FEL96YA;64@/2!.54Q,
    M.PH@"41E9D5L96T@(" @*F9O<F-E7VYO=%]N=6QL(#T@3E5,3#L*( E,:7-T
    M"2 @("IO=&AE<E]O<'1I;VYS(#T@3DE,.PHK"41E9D5L96T)(" @*G9A;&ED
    M871E7V1A=&%?9FEL92 ]($Y53$P["B )3&ES=$-E;&P@(" J8V5L;#L*( H@
    M"2\J"D! ("TR,S<L.2 K,C0U+#D@0$ @9FEL95]F9'=?=F%L:61A=&]R*%!'
    M7T953D-424].7T%21U,I"B )"7T*( H@"0DO*@HM"0D@*B!397!A<F%T92!O
    M=70@9FEL96YA;64@86YD(&9O<F-E7VYO=%]N=6QL+"!S:6YC92!0<F]C97-S
    M0V]P>4]P=&EO;G,*+0D)("H@=V]N)W0@86-C97!T('1H96TN(" H9F]R8V5?
    M;F]T7VYU;&P@;VYL>2!C;VUE<R!I;B!A(&)O;VQE86X*+0D)("H@<&5R+6-O
    M;'5M;B!F;&%V;W(@:&5R92XI"BL)"2 J(%-E<&%R871E(&]U="!F:6QE;F%M
    M92P@9F]R8V5?;F]T7VYU;&P@86YD('9A;&ED871E7V1A=&%?9FEL92P@<VEN
    M8V4**PD)("H@4')O8V5S<T-O<'E/<'1I;VYS('=O;B=T(&%C8V5P="!T:&5M
    M+B @*&9O<F-E7VYO=%]N=6QL(&]N;'D@8V]M97,@:6X**PD)("H@82!B;V]L
    M96%N('!E<BUC;VQU;6X@9FQA=F]R(&AE<F4N*0H@"0D@*B\*( D):68@*'-T
    M<F-M<"AD968M/F1E9FYA;64L(")F:6QE;F%M92(I(#T](# I"B )"7L*0$ @
    M+3(U.2PV("LR-C<L,38@0$ @9FEL95]F9'=?=F%L:61A=&]R*%!'7T953D-4
    M24].7T%21U,I"B )"0DO*B!$;VXG="!C87)E('=H870@=&AE('9A;'5E(&ES
    M+"!A<R!L;VYG(&%S(&ET)W,@82!L96=A;"!B;V]L96%N("HO"B )"0DH=F]I
    M9"D@9&5F1V5T0F]O;&5A;BAD968I.PH@"0E]"BL)"65L<V4@:68@*'-T<F-M
    M<"AD968M/F1E9FYA;64L(")V86QI9&%T95]D871A7V9I;&4B*2 ]/2 P*0HK
    M"0E["BL)"0EI9B H=F%L:61A=&5?9&%T85]F:6QE*0HK"0D)"65R97!O<G0H
    M15)23U(L"BL)"0D)"0DH97)R8V]D92A%4E)#3T1%7U-93E1!6%]%4E)/4BDL
    M"BL)"0D)"0D@97)R;7-G*")C;VYF;&EC=&EN9R!O<B!R961U;F1A;G0@;W!T
    M:6]N<R(I*2D["BL)"0EV86QI9&%T95]D871A7V9I;&4@/2!D968["BL)"0DO
    M*B!$;VXG="!C87)E('=H870@=&AE('9A;'5E(&ES+"!A<R!L;VYG(&%S(&ET
    M)W,@82!L96=A;"!B;V]L96%N("HO"BL)"0DH=F]I9"D@9&5F1V5T0F]O;&5A
    M;BAD968I.PHK"0E]"B )"65L<V4*( D)"6]T:&5R7V]P=&EO;G,@/2!L87!P
    M96YD*&]T:&5R7V]P=&EO;G,L(&1E9BD["B )?0I 0" M,CDY+#$Y("LS,3<L
    M,C,@0$ @:7-?=F%L:61?;W!T:6]N*&-O;G-T(&-H87(@*F]P=&EO;BP@3VED
    M(&-O;G1E>'0I"B O*@H@("H@1F5T8V@@=&AE(&]P=&EO;G,@9F]R(&$@9FEL
    M95]F9'<@9F]R96EG;B!T86)L92X*(" J"BT@*B!792!H879E('1O('-E<&%R
    M871E(&]U=" B9FEL96YA;64B(&9R;VT@=&AE(&]T:&5R(&]P=&EO;G,@8F5C
    M875S90HM("H@:70@;75S="!N;W0@87!P96%R(&EN('1H92!O<'1I;VYS(&QI
    M<W0@<&%S<V5D('1O('1H92!C;W)E($-/4%D@8V]D92X**R J(%=E(&AA=F4@
    M=&\@<V5P87)A=&4@;W5T(")F:6QE;F%M92(@86YD(")V86QI9&%T95]D871A
    M7V9I;&4B(&9R;VT@=&AE(&]T:&5R"BL@*B!O<'1I;VYS(&)E8V%U<V4@:70@
    M;75S="!N;W0@87!P96%R(&EN('1H92!O<'1I;VYS(&QI<W0@<&%S<V5D('1O
    M('1H92!C;W)E"BL@*B!#3U!9(&-O9&4N"B @*B\*('-T871I8R!V;VED"B!F
    M:6QE1V5T3W!T:6]N<RA/:60@9F]R96EG;G1A8FQE:60L"BT)"0D@("!C:&%R
    M("HJ9FEL96YA;64L($QI<W0@*BIO=&AE<E]O<'1I;VYS*0HK"0D)(" @8VAA
    M<B J*F9I;&5N86UE+ HK"0D)(" @3&ES=" J*F]T:&5R7V]P=&EO;G,L"BL)
    M"0D@("!B;V]L("IV86QI9&%T95]D871A7V9I;&4I"B!["B )1F]R96EG;E1A
    M8FQE("IT86)L93L*( E&;W)E:6=N4V5R=F5R("IS97)V97(["B )1F]R96EG
    M;D1A=&%7<F%P<&5R("IW<F%P<&5R.PH@"4QI<W0)(" @*F]P=&EO;G,["B )
    M3&ES=$-E;&P@(" J;&,L"BT)"0D@(" J<')E=CL**PD)"2 @("IP<F5V+ HK
    M"0D)(" @*FYE>'0["B *( DO*@H@"2 J($5X=')A8W0@;W!T:6]N<R!F<F]M
    M($9$5R!O8FIE8W1S+B @5V4@:6=N;W)E('5S97(@;6%P<&EN9W,@8F5C875S
    M90I 0" M,S,R+#(Q("LS-30L,S @0$ @9FEL94=E=$]P=&EO;G,H3VED(&9O
    M<F5I9VYT86)L96ED+ H@"6]P=&EO;G,@/2!L:7-T7V-O;F-A="AO<'1I;VYS
    M+"!G971?9FEL95]F9'=?871T<FEB=71E7V]P=&EO;G,H9F]R96EG;G1A8FQE
    M:60I*3L*( H@"2\J"BT)("H@4V5P87)A=&4@;W5T('1H92!F:6QE;F%M92X*
    M*PD@*B!397!A<F%T92!O=70@=&AE(&9I;&5N86UE(&%N9"!D871A(&9I;&4@
    M=F%L:61A=&EO;B!O<'1I;VXN"B )("HO"B )*F9I;&5N86UE(#T@3E5,3#L*
    M*PEI9B H=F%L:61A=&5?9&%T85]F:6QE*0HK"0DJ=F%L:61A=&5?9&%T85]F
    M:6QE(#T@9F%L<V4["B )<')E=B ]($Y53$P["BT)9F]R96%C:"AL8RP@;W!T
    M:6]N<RD**PEF;W(@*&QC(#T@;&ES=%]H96%D*&]P=&EO;G,I.R!L8SL@;&,@
    M/2!N97AT*0H@"7L*( D)1&5F16QE;2 @(" J9&5F(#T@*$1E9D5L96T@*BD@
    M;&9I<G-T*&QC*3L*( HK"0EN97AT(#T@;&YE>'0H;&,I.PH@"0EI9B H<W1R
    M8VUP*&1E9BT^9&5F;F%M92P@(F9I;&5N86UE(BD@/3T@,"D*( D)>PH@"0D)
    M*F9I;&5N86UE(#T@9&5F1V5T4W1R:6YG*&1E9BD["B )"0EO<'1I;VYS(#T@
    M;&ES=%]D96QE=&5?8V5L;"AO<'1I;VYS+"!L8RP@<')E=BD["BT)"0EB<F5A
    M:SL*( D)?0HM"0EP<F5V(#T@;&,["BL)"65L<V4@:68@*'-T<F-M<"AD968M
    M/F1E9FYA;64L(")V86QI9&%T95]D871A7V9I;&4B*2 ]/2 P*0HK"0E["BL)
    M"0EI9B H=F%L:61A=&5?9&%T85]F:6QE*0HK"0D)"2IV86QI9&%T95]D871A
    M7V9I;&4@/2!D969'971";V]L96%N*&1E9BD["BL)"0EO<'1I;VYS(#T@;&ES
    M=%]D96QE=&5?8V5L;"AO<'1I;VYS+"!L8RP@<')E=BD["BL)"7T**PD)96QS
    M90HK"0D)<')E=B ](&QC.PH@"7T*( H@"2\J"D! ("TT,S0L-R K-#8U+#D@
    M0$ @9FEL94=E=$9O<F5I9VY296Q3:7IE*%!L86YN97));F9O("IR;V]T+ H@
    M"2 J+PH@"69D=U]P<FEV871E(#T@*$9I;&5&9'=0;&%N4W1A=&4@*BD@<&%L
    M;&]C*'-I>F5O9BA&:6QE1F1W4&QA;E-T871E*2D["B )9FEL94=E=$]P=&EO
    M;G,H9F]R96EG;G1A8FQE:60L"BT)"0D)(" @)F9D=U]P<FEV871E+3YF:6QE
    M;F%M92P@)F9D=U]P<FEV871E+3YO<'1I;VYS*3L**PD)"0D@(" F9F1W7W!R
    M:79A=&4M/F9I;&5N86UE+ HK"0D)"2 @("9F9'=?<')I=F%T92T^;W!T:6]N
    M<RP**PD)"0D@("!.54Q,*3L*( EB87-E<F5L+3YF9'=?<')I=F%T92 ]("AV
    M;VED("HI(&9D=U]P<FEV871E.PH@"B )+RH@17-T:6UA=&4@<F5L871I;VX@
    M<VEZ92 J+PI 0" M-3(R+#<@*S4U-2PY($! (&9I;&5%>'!L86EN1F]R96EG
    M;E-C86XH1F]R96EG;E-C86Y3=&%T92 J;F]D92P@17AP;&%I;E-T871E("IE
    M<RD*( H@"2\J($9E=&-H(&]P=&EO;G,@+2TM('=E(&]N;'D@;F5E9"!F:6QE
    M;F%M92!A="!T:&ES('!O:6YT("HO"B )9FEL94=E=$]P=&EO;G,H4F5L871I
    M;VY'971296QI9"AN;V1E+3YS<RYS<U]C=7)R96YT4F5L871I;VXI+ HM"0D)
    M"2 @("9F:6QE;F%M92P@)F]P=&EO;G,I.PHK"0D)"2 @("9F:6QE;F%M92P*
    M*PD)"0D@(" F;W!T:6]N<RP**PD)"0D@("!.54Q,*3L*( H@"45X<&QA:6Y0
    M<F]P97)T>51E>'0H(D9O<F5I9VX@1FEL92(L(&9I;&5N86UE+"!E<RD["B *
    M0$ @+34T-RPV("LU.#(L-R! 0"!F:6QE0F5G:6Y&;W)E:6=N4V-A;BA&;W)E
    M:6=N4V-A;E-T871E("IN;V1E+"!I;G0@969L86=S*0H@"6-H87()(" @*F9I
    M;&5N86UE.PH@"4QI<W0)(" @*F]P=&EO;G,["B )0V]P>5-T871E"6-S=&%T
    M93L**PEB;V]L"0EV86QI9&%T95]D871A7V9I;&4["B )1FEL949D=T5X96-U
    M=&EO;E-T871E("IF97-T871E.PH@"B )+RH*0$ @+34U-RPW("LU.3,L.2! 
    M0"!F:6QE0F5G:6Y&;W)E:6=N4V-A;BA&;W)E:6=N4V-A;E-T871E("IN;V1E
    M+"!I;G0@969L86=S*0H@"B )+RH@1F5T8V@@;W!T:6]N<R!O9B!F;W)E:6=N
    M('1A8FQE("HO"B )9FEL94=E=$]P=&EO;G,H4F5L871I;VY'971296QI9"AN
    M;V1E+3YS<RYS<U]C=7)R96YT4F5L871I;VXI+ HM"0D)"2 @("9F:6QE;F%M
    M92P@)F]P=&EO;G,I.PHK"0D)"2 @("9F:6QE;F%M92P**PD)"0D@(" F;W!T
    M:6]N<RP**PD)"0D@(" F=F%L:61A=&5?9&%T85]F:6QE*3L*( H@"2\J"B )
    M("H@0W)E871E($-O<'E3=&%T92!F<F]M($9$5R!O<'1I;VYS+B @5V4@86QW
    M87ES(&%C<75I<F4@86QL(&-O;'5M;G,L('-O"D! ("TU-S8L-B K-C$T+#<@
    M0$ @9FEL94)E9VEN1F]R96EG;E-C86XH1F]R96EG;E-C86Y3=&%T92 J;F]D
    M92P@:6YT(&5F;&%G<RD*( EF97-T871E+3YF:6QE;F%M92 ](&9I;&5N86UE
    M.PH@"69E<W1A=&4M/F]P=&EO;G,@/2!O<'1I;VYS.PH@"69E<W1A=&4M/F-S
    M=&%T92 ](&-S=&%T93L**PEF97-T871E+3YV86QI9&%T95]D871A7V9I;&4@
    M/2!V86QI9&%T95]D871A7V9I;&4["B *( EN;V1E+3YF9'=?<W1A=&4@/2 H
    M=F]I9" J*2!F97-T871E.PH@?0I 0" M-3DP+#8@*S8R.2PX($! (&9I;&5)
    M=&5R871E1F]R96EG;E-C86XH1F]R96EG;E-C86Y3=&%T92 J;F]D92D*('L*
    M( E&:6QE1F1W17AE8W5T:6]N4W1A=&4@*F9E<W1A=&4@/2 H1FEL949D=T5X
    M96-U=&EO;E-T871E("HI(&YO9&4M/F9D=U]S=&%T93L*( E4=7!L951A8FQE
    M4VQO=" J<VQO=" ](&YO9&4M/G-S+G-S7U-C86Y4=7!L95-L;W0["BL)4F5L
    M871I;VX)<F5L(#T@;F]D92T^<W,N<W-?8W5R<F5N=%)E;&%T:6]N.PHK"51U
    M<&QE0V]N<W1R("IC;VYS='(@/2!R96PM/G)D7V%T="T^8V]N<W1R.PH@"6)O
    M;VP)"69O=6YD.PH@"45R<F]R0V]N=&5X=$-A;&QB86-K(&5R<F-O;G1E>'0[
    M"B *0$ @+38Q-BPW("LV-3<L,3$@0$ @9FEL94ET97)A=&5&;W)E:6=N4V-A
    M;BA&;W)E:6=N4V-A;E-T871E("IN;V1E*0H@"0D)"0D)('-L;W0M/G1T<U]V
    M86QU97,L('-L;W0M/G1T<U]I<VYU;&PL"B )"0D)"0D@3E5,3"D["B ):68@
    M*&9O=6YD*0HK"7L*( D)17AE8U-T;W)E5FER='5A;%1U<&QE*'-L;W0I.PHK
    M"0EI9B H8V]N<W1R("8F(&-O;G-T<BT^:&%S7VYO=%]N=6QL("8F(&9E<W1A
    M=&4M/G9A;&ED871E7V1A=&%?9FEL92D**PD)"45X96-.;W1.=6QL0VAE8VLH
    M<F5L+"!S;&]T*3L**PE]"B *( DO*B!296UO=F4@97)R;W(@8V%L;&)A8VLN
    M("HO"B )97)R;W)?8V]N=&5X=%]S=&%C:R ](&5R<F-O;G1E>'0N<')E=FEO
    M=7,["D! ("TV-CDL-R K-S$T+#<@0$ @9FEL94%N86QY>F5&;W)E:6=N5&%B
    M;&4H4F5L871I;VX@<F5L871I;VXL"B )<W1R=6-T('-T870@<W1A=%]B=68[
    M"B *( DO*B!&971C:"!O<'1I;VYS(&]F(&9O<F5I9VX@=&%B;&4@*B\*+0EF
    M:6QE1V5T3W!T:6]N<RA296QA=&EO;D=E=%)E;&ED*')E;&%T:6]N*2P@)F9I
    M;&5N86UE+" F;W!T:6]N<RD["BL)9FEL94=E=$]P=&EO;G,H4F5L871I;VY'
    M971296QI9"AR96QA=&EO;BDL("9F:6QE;F%M92P@)F]P=&EO;G,L($Y53$PI
    M.PH@"B )+RH*( D@*B!'970@<VEZ92!O9B!T:&4@9FEL92X@("A86%@@:68@
    M=V4@9F%I;"!H97)E+"!W;W5L9"!I="!B92!B971T97(@=&\@:G5S= I 0" M
    M.#0V+#<@*S@Y,2PW($! (&9I;&5?86-Q=6ER95]S86UP;&5?<F]W<RA296QA
    M=&EO;B!O;F5R96PL(&EN="!E;&5V96PL"B );G5L;',@/2 H8F]O;" J*2!P
    M86QL;V,H='5P1&5S8RT^;F%T=',@*B!S:7IE;V8H8F]O;"DI.PH@"B )+RH@
    M1F5T8V@@;W!T:6]N<R!O9B!F;W)E:6=N('1A8FQE("HO"BT)9FEL94=E=$]P
    M=&EO;G,H4F5L871I;VY'971296QI9"AO;F5R96PI+" F9FEL96YA;64L("9O
    M<'1I;VYS*3L**PEF:6QE1V5T3W!T:6]N<RA296QA=&EO;D=E=%)E;&ED*&]N
    M97)E;"DL("9F:6QE;F%M92P@)F]P=&EO;G,L($Y53$PI.PH@"B )+RH*( D@
    M*B!#<F5A=&4@0V]P>5-T871E(&9R;VT@1D17(&]P=&EO;G,N"F1I9F8@+2UG
    M:70@82]C;VYT<FEB+V9I;&5?9F1W+V]U='!U="]F:6QE7V9D=RYS;W5R8V4@
    M8B]C;VYT<FEB+V9I;&5?9F1W+V]U='!U="]F:6QE7V9D=RYS;W5R8V4*:6YD
    M97@@-F8Y,#9E,2XN,C5A93EF-R Q,# V-#0*+2TM(&$O8V]N=')I8B]F:6QE
    M7V9D=R]O=71P=70O9FEL95]F9'<N<V]U<F-E"BLK*R!B+V-O;G1R:6(O9FEL
    M95]F9'<O;W5T<'5T+V9I;&5?9F1W+G-O=7)C90I 0" M,3(S+#<@*S$R,RPW
    M($! ($524D]2.B @:6YV86QI9"!O<'1I;VX@(F9O<F-E7VYO=%]N=6QL(@H@
    M2$E.5#H@(%1H97)E(&%R92!N;R!V86QI9"!O<'1I;VYS(&EN('1H:7,@8V]N
    M=&5X="X*($-214%412!&3U)%24=.(%1!0DQ%('1B;" H*2!315)615(@9FEL
    M95]S97)V97(@3U!424].4R H9F]R8V5?;F]T7VYU;&P@)RHG*3L@+2T@15)2
    M3U(*($524D]2.B @:6YV86QI9"!O<'1I;VX@(F9O<F-E7VYO=%]N=6QL(@HM
    M2$E.5#H@(%9A;&ED(&]P=&EO;G,@:6X@=&AI<R!C;VYT97AT(&%R93H@9FEL
    M96YA;64L(&9O<FUA="P@:&5A9&5R+"!D96QI;6ET97(L('%U;W1E+"!E<V-A
    M<&4L(&YU;&PL(&5N8V]D:6YG"BM(24Y4.B @5F%L:60@;W!T:6]N<R!I;B!T
    M:&ES(&-O;G1E>'0@87)E.B!F:6QE;F%M92P@9F]R;6%T+"!H96%D97(L(&1E
    M;&EM:71E<BP@<75O=&4L(&5S8V%P92P@;G5L;"P@96YC;V1I;F<L('9A;&ED
    M871E7V1A=&%?9FEL90H@+2T@8F%S:6,@<75E<GD@=&5S=',*(%-%3$5#5" J
    M($923TT@86=G7W1E>'0@5TA%4D4@8B ^(#$P+C @3U)$15(@0ED@83L*(" @
    M82 @?" @(&(@(" @"F1I9F8@+2UG:70@82]D;V,O<W)C+W-G;6PO9FEL92UF
    M9'<N<V=M;"!B+V1O8R]S<F,O<V=M;"]F:6QE+69D=RYS9VUL"FEN9&5X(#@X
    M.6%A-S<N+C4T-3$X,&4@,3 P-C0T"BTM+2!A+V1O8R]S<F,O<V=M;"]F:6QE
    M+69D=RYS9VUL"BLK*R!B+V1O8R]S<F,O<V=M;"]F:6QE+69D=RYS9VUL"D! 
    M("TQ,#@L-B K,3 X+#$V($! "B @(" \+VQI<W1I=&5M/@H@(" \+W9A<FQI
    M<W1E;G1R>3X*( HK(" \=F%R;&ES=&5N=')Y/@HK(" @/'1E<FT^/&QI=&5R
    M86P^=F%L:61A=&5?9&%T85]F:6QE/"]L:71E<F%L/CPO=&5R;3X**PHK(" @
    M/&QI<W1I=&5M/@HK(" @(#QP87)A/@HK(" @("!3<&5C:69I97,@=VAE=&AE
    M<B!T:&4@/&QI=&5R86P^3D]4($Y53$P\+VQI=&5R86P^(&-O;G-T<F%I;G0@
    M:7,@=F%L:61A=&5D+@HK(" @(#PO<&%R83X**R @(#PO;&ES=&ET96T^"BL@
    M(#PO=F%R;&ES=&5N=')Y/@HK"B @/"]V87)I86)L96QI<W0^"B *(" \<&%R
    M83X*9&EF9B M+6=I="!A+W-R8R]B86-K96YD+V5X96-U=&]R+V5X96--86EN
    M+F,@8B]S<F,O8F%C:V5N9"]E>&5C=71O<B]E>&5C36%I;BYC"FEN9&5X(#0T
    M,#0S.&(N+F8Q,#=B,S$@,3 P-C0T"BTM+2!A+W-R8R]B86-K96YD+V5X96-U
    M=&]R+V5X96--86EN+F,**RLK(&(O<W)C+V)A8VME;F0O97AE8W5T;W(O97AE
    M8TUA:6XN8PI 0" M,30S."PV("LQ-#,X+#(X($! ($5X96-U=&50;&%N*$53
    M=&%T92 J97-T871E+ H@"B *("\J"BL@*B!%>&5C3F]T3G5L;$-H96-K("TM
    M+2!C:&5C:R!T:&%T('1U<&QE(&UE971S($Y/5"!.54Q,(&-O;G-T<F%I;G1S
    M"BL@*B\**W9O:60**T5X96-.;W1.=6QL0VAE8VLH4F5L871I;VX@<F5L+"!4
    M=7!L951A8FQE4VQO=" J<VQO="D**WL**PEI;G0)"0EN871T<R ](')E;"T^
    M<F1?871T+3YN871T<SL**PEI;G0)"0EA='1R0VAK.PHK"BL)9F]R("AA='1R
    M0VAK(#T@,3L@871T<D-H:R \/2!N871T<SL@871T<D-H:RLK*0HK"7L**PD)
    M:68@*')E;"T^<F1?871T+3YA='1R<UMA='1R0VAK("T@,5TM/F%T=&YO=&YU
    M;&P@)B8**PD)"7-L;W1?871T:7-N=6QL*'-L;W0L(&%T=')#:&LI*0HK"0D)
    M97)E<&]R="A%4E)/4BP**PD)"0D)*&5R<F-O9&4H15)20T]$15].3U1?3E5,
    M3%]624],051)3TXI+ HK"0D)"0D@97)R;7-G*")N=6QL('9A;'5E(&EN(&-O
    M;'5M;B!<(B5S7"(@=FEO;&%T97,@;F]T+6YU;&P@8V]N<W1R86EN="(L"BL)
    M"0D)"0D)3F%M95-T<BAR96PM/G)D7V%T="T^871T<G-;871T<D-H:R M(#%=
    M+3YA='1N86UE*2DL"BL)"0D)"2!E<G)D971A:6PH(D9A:6QI;F<@<F]W(&-O
    M;G1A:6YS("5S+B(L"BL)"0D)"0D)(" @17AE8T)U:6QD4VQO=%9A;'5E1&5S
    M8W)I<'1I;VXH<VQO="P@-C0I*2DI.PHK"7T**WT**PHK+RH*(" J($5X96-2
    M96Q#:&5C:R M+2T@8VAE8VL@=&AA="!T=7!L92!M965T<R!C;VYS=')A:6YT
    M<R!F;W(@<F5S=6QT(')E;&%T:6]N"B @*B\*('-T871I8R!C;VYS="!C:&%R
    M("H*0$ @+3$U,#DL,C(@*S$U,S$L-R! 0"!%>&5C0V]N<W1R86EN=',H4F5S
    M=6QT4F5L26YF;R J<F5S=6QT4F5L26YF;RP*( E!<W-E<G0H8V]N<W1R*3L*
    M( H@"6EF("AC;VYS='(M/FAA<U]N;W1?;G5L;"D*+0E["BT)"6EN= D)"6YA
    M='1S(#T@<F5L+3YR9%]A='0M/FYA='1S.PHM"0EI;G0)"0EA='1R0VAK.PHM
    M"BT)"69O<B H871T<D-H:R ](#$[(&%T=')#:&L@/#T@;F%T=',[(&%T=')#
    M:&LK*RD*+0D)>PHM"0D):68@*')E;"T^<F1?871T+3YA='1R<UMA='1R0VAK
    M("T@,5TM/F%T=&YO=&YU;&P@)B8*+0D)"0ES;&]T7V%T=&ES;G5L;"AS;&]T
    M+"!A='1R0VAK*2D*+0D)"0EE<F5P;W)T*$524D]2+ HM"0D)"0D)*&5R<F-O
    M9&4H15)20T]$15].3U1?3E5,3%]624],051)3TXI+ HM"0D)"0D)(&5R<FUS
    M9R@B;G5L;"!V86QU92!I;B!C;VQU;6X@7"(E<UPB('9I;VQA=&5S(&YO="UN
    M=6QL(&-O;G-T<F%I;G0B+ HM"0D)"0D)("!.86UE4W1R*')E;"T^<F1?871T
    M+3YA='1R<UMA='1R0VAK("T@,5TM/F%T=&YA;64I*2P*+0D)"0D)"2!E<G)D
    M971A:6PH(D9A:6QI;F<@<F]W(&-O;G1A:6YS("5S+B(L"BT)"0D)"0D)"2 @
    M($5X96-"=6EL9%-L;W1686QU941E<V-R:7!T:6]N*'-L;W0L(#8T*2DI*3L*
    M+0D)?0HM"7T**PD)17AE8TYO=$YU;&Q#:&5C:RAR96PL('-L;W0I.PH@"B )
    M:68@*&-O;G-T<BT^;G5M7V-H96-K(#X@,"D*( E["F1I9F8@+2UG:70@82]S
    M<F,O:6YC;'5D92]E>&5C=71O<B]E>&5C=71O<BYH(&(O<W)C+VEN8VQU9&4O
    M97AE8W5T;W(O97AE8W5T;W(N: II;F1E>" P-S5B8F4X+BXS869D9CDX(#$P
    M,#8T- HM+2T@82]S<F,O:6YC;'5D92]E>&5C=71O<B]E>&5C=71O<BYH"BLK
    M*R!B+W-R8R]I;F-L=61E+V5X96-U=&]R+V5X96-U=&]R+F@*0$ @+3$X."PV
    M("LQ.#@L-R! 0"!E>'1E<FX@=F]I9"!);FET4F5S=6QT4F5L26YF;RA297-U
    M;'1296Q);F9O("IR97-U;'1296Q);F9O+ H@"0D)"2 @:6YT(&EN<W1R=6UE
    M;G1?;W!T:6]N<RD["B!E>'1E<FX@4F5S=6QT4F5L26YF;R J17AE8T=E=%1R
    M:6=G97)297-U;'1296PH15-T871E("IE<W1A=&4L($]I9"!R96QI9"D["B!E
    M>'1E<FX@8F]O;"!%>&5C0V]N=&5X=$9O<F-E<T]I9',H4&QA;E-T871E("IP
    M;&%N<W1A=&4L(&)O;VP@*FAA<V]I9',I.PHK97AT97)N('9O:60@17AE8TYO
    M=$YU;&Q#:&5C:RA296QA=&EO;B!R96PL(%1U<&QE5&%B;&53;&]T("IS;&]T
    M*3L*(&5X=&5R;B!V;VED($5X96-#;VYS=')A:6YT<RA297-U;'1296Q);F9O
    M("IR97-U;'1296Q);F9O+ H@"0D)"51U<&QE5&%B;&53;&]T("IS;&]T+"!%
    M4W1A=&4@*F5S=&%T92D["B!E>'1E<FX@17AE8U)O=TUA<FL@*D5X96-&:6YD
    D4F]W36%R:RA%4W1A=&4@*F5S=&%T92P@26YD97@@<G1I*3L*
    `
    end