<commit_before>=head1 NAME

 SQL::Struct - convenience SQL functions with Class::Struct-like row objects

=head1 SYNOPSIS

    use SQL::Struct;

    SQL::Struct::connect($data_source, $username, $auth);

    my $row = one_row("table", $idField);

    print $row->field;

    $row->field('new data');

    $row->update;

    my $rows = all_rows("table", {field => "some data"});

    print $rows->[0]->field;

=head1 DESCRIPTION

Makes SQL queries from Perl data structures. It uses L<SQL::Abstract> module to 
parse "where" and "order by" structures. It also supports "group by", "having", 
"limit", "offset" and mapping function. To make actual queries subclass of 
L<DBIx::Connector> is used. This class and its singleton connector object can be
pluggable. 

=head2 connect($data_source, $username, $auth)

This method connects to database or returns already connected connector object.
For every table in database there's one corresponding class in DBC:: namespaece 
in CamelCase style after successful connect created. E.g. DBC::ClientData is 
created for table "client_data".

=head2 one_row($table, $abstract_where, $order_by, $limit, $offset)

Selects one row from given table and returns its object. $table can be a simple 
table name or returning data query expression. In last case DBQ:: namespace is 
used to name class of row object of such a query.

There are some named paramters can be used together with positional paramaters:

=over

=item -group_by

Generates "GROUP BY" SQL-clause

 my $row1 = one_row("table", -group_by => "field");

Generates and executes "select * from table group by field" SQL-statement. 
 
 my $row2 = one_row("table", -group_by => [qw|field field2|]);
 
Generates and executes "select * from table group by field, field2" SQL-statement.
Returns one row object.

=item -having

Adds "HAVING" conditions to "GROUP BY"
 
 my $row1 = one_row("table", -group_by => "field", -having => {"length(field)" => {">", 5} });

=item -order_by

Generates "ORDER BY" SQL-clause as in L<SQL::Abstract>.

=item -where

Generates "WHERE" SQL-clause as in L<SQL::Abstract>. If $abstract_where is just a scalar
then it is supposed to be a primary key value.

=item -limit

=item -offset

Generates "LIMIT $X OFFSET $Y" SQL-clause.

=back

=head2 all_rows($table, $abstract_where, $order_by, $limit, $offset)

This is just like previous C<one_row> but returns array of row objects. 
It has one more "floating" parameter: you can specify CODE reference in any 
place and it will be used as "mapping function".

    my $rows =  all_rows("table", 
                     { date => {'>=', \"now() - interval '1 hour'"}, 
                     sub {$_->filter_timestamp; $_->data});

This anonymous function is called for every row clearing timestamps from microseconds part 
and converting every row object into anonymous hash.

=head2 new_row("table", column => $value, column2 => $value2, ...)

Inserts new row into table. Returns row object with set primary columns and passed in 
C<new_row> subroutine. If you need to set all columns from table then:

    my $row = new_row("table", column => $value);
    $row->fetch;

=head1 Row object methods

=head2 new

Creates new row in the table. This is the same as C<new_row()> except table name is already 
known from class name. 

    my $row = DBC::Table->new(email => '<EMAIL>', password => '<PASSWORD>');

=head2 set

Sets values of table columns. Has three forms:

=over

=item set([...])

 Sets internal row data.
 
=item set({column => $value, ... })

 Sets column(s) value(s)
 
=item set(column => $value, ... )

 Same as above but without anonymous hash.
 
=back

This method is useful when you can't use accessors. For example, when you 
have column name 'new' in your table.

=head2 data

Returns values of the row. Hash four forms:

=over

=item data()

 No parameters means to return all columns in anonymous hash {column => "value", ... }.

=item data([])

 Empty array reference means internal row data.
 
=item data([qw|column columnt2|])

 Non-empty array means array of values for corresponding columns.
 
=item data({column => undef, columnt2 => undef})

 Returns given columns set in anonymous hash {column => "value", ... }.

=back

=head2 update

=head2 delete

=head2 filter_timestamp

=head2 fetch

=head2 accessors

=head2 Syntax sugar

=head3 referenced table

=head3 referenced by table

=cut
<commit_msg>update docs<commit_after>=head1 NAME

 SQL::Struct - convenience SQL functions with Class::Struct-like row objects

=head1 SYNOPSIS

    use SQL::Struct;

    SQL::Struct::connect($data_source, $username, $auth);

    my $row = one_row("table", $idField);

    print $row->field;

    $row->field('new data');

    $row->update;

    my $rows = all_rows("table", {field => "some data"});

    print $rows->[0]->field;

=head1 DESCRIPTION

Makes SQL queries from Perl data structures. It uses L<SQL::Abstract> module to 
parse "where" and "order by" structures. It also supports "group by", "having", 
"limit", "offset" and mapping function. To make actual queries subclass of 
L<DBIx::Connector> is used. This class and its singleton connector object can be
pluggable. 

=head2 connect($data_source, $username, $auth)

This method connects to database or returns already connected connector object.
For every table in database there's one corresponding class in DBC:: namespaece 
in CamelCase style after successful connect created. E.g. DBC::ClientData is 
created for table "client_data".

=head2 one_row($table, $abstract_where, $order_by, $limit, $offset)

Selects one row from given table and returns its object. $table can be a simple 
table name or returning data query expression. In last case DBQ:: namespace is 
used to name class of row object of such a query.

There are some named paramters can be used together with positional paramaters:

=over

=item -group_by

Generates "GROUP BY" SQL-clause

 my $row1 = one_row("table", -group_by => "field");

Generates and executes "select * from table group by field" SQL-statement. 
 
 my $row2 = one_row("table", -group_by => [qw|field field2|]);
 
Generates and executes "select * from table group by field, field2" SQL-statement.
Returns one row object.

=item -having

Adds "HAVING" conditions to "GROUP BY"
 
 my $row1 = one_row("table", -group_by => "field", -having => {"length(field)" => {">", 5} });

=item -order_by

Generates "ORDER BY" SQL-clause as in L<SQL::Abstract>.

=item -where

Generates "WHERE" SQL-clause as in L<SQL::Abstract>. If $abstract_where is just a scalar
then it is supposed to be a primary key value.

=item -limit

=item -offset

Generates "LIMIT $X OFFSET $Y" SQL-clause.

=back

=head2 all_rows($table, $abstract_where, $order_by, $limit, $offset)

This is just like previous C<one_row> but returns array of row objects. 
It has one more "floating" parameter: you can specify CODE reference in any 
place and it will be used as "mapping function".

    my $rows =  all_rows("table", 
                     { date => {'>=', \"now() - interval '1 hour'"}, 
                     sub {$_->filter_timestamp; $_->data});

This anonymous function is called for every row clearing timestamps from microseconds part 
and converting every row object into anonymous hash.

=head2 new_row("table", column => $value, column2 => $value2, ...)

Inserts new row into table. Returns row object with set primary columns and passed in 
C<new_row> subroutine. If you need to set all columns from table then:

    my $row = new_row("table", column => $value);
    $row->fetch;

=head1 Row object methods

=head2 new

Creates new row in the table. This is the same as C<new_row()> except table name is already 
known from class name. 

    my $row = DBC::Table->new(email => '<EMAIL>', password => '<PASSWORD>');

=head2 set

Sets values of table columns. Has three forms:

=over

=item set([...])

 Sets internal row data.
 
=item set({column => $value, ... })

 Sets column(s) value(s)
 
=item set(column => $value, ... )

 Same as above but without anonymous hash.
 
=back

This method is useful when you can't use accessors. For example, when you 
have column name 'new' in your table.

=head2 data

Returns values of the row. Has four forms:

=over

=item data()

 No parameters means to return all columns in anonymous hash {column => "value", ... }.

=item data([])

 Empty array reference means internal row data.
 
=item data([qw|column columnt2|])

 Non-empty array means array of values for corresponding columns.
 
=item data({column => undef, columnt2 => undef})

 Returns given columns set in anonymous hash {column => "value", ... }.

=back

=head2 update

Updates its row or table

=over

=item update()

Updates changed (if any) columns of the row.

=item update({column => "value"}, $where)

Updates table. For example:

 DBC::List->update({ref => 33}, {id => 1});
 
Means 
 
 update list ref = ?  WHERE ( id = ? )

with bind values 33, 1

=back

=head2 delete

Deletes the row or rows from the table.

=over

=item delete()

Deletes the row if the row has primary key.

=item delete( $where)

deletes row(s) from table. For example:

 DBC::List->delete({id => 1});
 
Means 
 
 delete from list WHERE ( id = ? )

with bind value 1

=back

=head2 filter_timestamp

Removes microseconds from timestamp columns. 
 
 2010-05-19 23:30:01.737126 -> 2010-05-19 23:30:01

=head2 fetch

Fetches the whole row data from table. Useful when primary key is known after
insert but other columns are set by database.

=head2 accessors

All column names from table except special keywords are accessible via accessors:

=over

 my $prim = one_row("prim", 1);
 print "payload: " .  $prim->payload . "\n";
 # new data
 $prim->payload("pay never");
 $prim->update;
 
Here $prim->payload("pay never") sets new column value. To store it explicitly 
call $prim->update. By default update is called on row object destruction.

=back

=head1 Syntax sugar

=head2 referenced table

=head2 referenced by table

=cut

{'fraction_non_alphanumeric': 0.11259274112693002, 'fraction_numerical': 0.010527371165029076, 'mean_word_length': 3.8398835516739447, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2179471', 'n_tokens_mistral': 3178, 'n_tokens_neox': 3006, 'n_words': 1293}