=encoding utf-8

=head1 NAME

DB::Object::Query::Clause - SQL Query Clause Object

=head1 SYNOPSIS

    my $clause = DB::Object::Query::Clause->new({
        value => "$field != '$user'",
        generic => "$field != ?",
        type => 'where',
        # or possibly:
        # bind => 
        # {
        #     values => $values_array_ref,
        #     types => $types_array_ref
        # }
    })
    # A DB::Object::Query object
    $clause->query_object( $q );
    $clause->bind->values( $res );
    $clause->bind->types( '' );
    $clause->fields( $field ) if( Scalar::Util::blessed( $field ) && $field->isa( 'DB::Object::Fields::Field' ) );

Merging multiple clauses

    $clause = DB::Object::Query::Clause->new->merge( $dbh->AND( @clauses ) );
    $clause->bind->values( @values ) if( $bind );
    $clause->bind->types( @types ) if( $bind );

Get the clause stringified

    my $sql = "SELECT * FROM my_table WHERE $clause";

This could become something like:

    SELECT * FROM my_table WHERE username != 'joe' AND username != 'bob'

However if binding values is activated, this would rather become:

    SELECT * FROM my_table WHERE username != ? AND username != ?

And the associated values would be automatically bound to the query upon execution

=head1 VERSION

v0.1.0

=head1 DESCRIPTION

The purpose of this module is to contain various attributes of a SQL clause so that it can be accessed and manipulated flexibly.

It will not create SQL query. This is done by the calling module and the query is stored in the I<value> parameter which is also the L</"value"> method

This is used to contain clauses such as I<group>, I<having>, I<limit>, I<order>, I<where>

=head1 METHODS

=head2 new

It can take the following properties that can also be accessed as method:

=over 4

=item I<value>

The sql query fragment string

=item I<generic>

The sql fragment with placeholders, for example:

    username = ?

=item I<bind>

Provided a hash with the following properties:

=over 8

=item I<values>

The values to bind as an array reference

=item I<types>

The SQL types of the values to bind as an array reference

=back

=back

=head2 as_string

This returns the clause as a string.

This is also called when the object is used as a string

    print( "SQL query is: SELECT * FROM my_table WHERE $clause\n")

If field objects were used such as:

    $dbh->NOT( $user_tbl->fo->username => 'Bob' );

Then if needed, B<as_string> would prefix the field name with its associated table name

=head2 fields

An array reference of field objects (L<DB::Object::Fields::Field>)

The array itself is an object from L<Module::Generic::Array>

=head2 generic

Returns a string representing the sql fragment with placeholder.

The string returned is an object of L<Module::Generic::Scalar>

=head2 length

Returns the length of the string in L</"value">

=head2 metadata

Set or get an hash reference accessible as a dynamic class object from L<DB::Object::Query::Clause::Metadata>

=head2 merge

Given an array of clauses, this will merge them into one new clause object.

If the first value of the array is a L<DB::Object::Operator> such as L<DB::Object::Operator::AND> or L<DB::Object::Operator::OR>, the list will be taken from this object and the resulting sql statement will the operator value, ie C<AND> or C<OR> for example

=head2 query_object

Set or get the L<DB::Object::Query> object, which normally would have created this clause object.

=head2 type

Set or get the type of clause this is, such as I<group>, I<having>, I<limit>, I<order>, I<where>

The return value is a string that can be accessed as an object of L<Module::Generic::Scalar>

=head2 value

The SQL fragment as a string. The return value is a string that can be accessed as an object of L<Module::Generic::Scalar>

=head1 SEE ALSO

L<DB::Object::Query>, L<DB::Object::Mysql::Query>, L<DB::Object::Postgres::Query>, L<DB::Object::SQLite::Query>

=head1 AUTHOR

Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>

=head1 COPYRIGHT & LICENSE

Copyright (c) 2019-2021 DEGUEST Pte. Ltd.

You can use, copy, modify and redistribute this package and associated
files under the same terms as Perl itself.

=cut
