Mojo-SQL-0.02/0000755000076500000240000000000015200733313011451 5ustar sristaffMojo-SQL-0.02/LICENSE0000644000076500000240000000207315200323441012455 0ustar sristaffThe MIT License (MIT) Copyright (c) 2026 Sebastian Riedel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Mojo-SQL-0.02/Changes0000644000076500000240000000021415200733031012736 0ustar sristaff 0.02 2026-05-12 - Added support for escaping literal question marks with ?? in sql and sql_unsafe. 0.01 2026-05-09 - First release. Mojo-SQL-0.02/MANIFEST0000644000076500000240000000051415200733313012602 0ustar sristaff.perltidyrc Changes lib/Mojo/SQL.pm lib/Mojo/SQL/Statement.pm LICENSE Makefile.PL MANIFEST This list of files README.md t/pod.t t/pod_coverage.t t/sql.t t/util.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Mojo-SQL-0.02/t/0000755000076500000240000000000015200733313011714 5ustar sristaffMojo-SQL-0.02/t/pod.t0000644000076500000240000000043115200334261012660 0ustar sristaffuse Mojo::Base -strict; use Test::More; plan skip_all => 'set TEST_POD to enable this test (developer only!)' unless $ENV{TEST_POD} || $ENV{TEST_ALL}; plan skip_all => 'Test::Pod 1.14+ required for this test!' unless eval 'use Test::Pod 1.14; 1'; all_pod_files_ok(); Mojo-SQL-0.02/t/sql.t0000644000076500000240000001652315200732720012710 0ustar sristaffuse Mojo::Base -strict, -signatures; use Test::More; use Mojo::SQL qw(sql sql_unsafe); use Mojo::SQL::Statement; subtest 'Statement' => sub { is_deeply(Mojo::SQL::Statement->new->parse('SELECT 1')->to_query, {text => 'SELECT 1', values => []}, 'static'); is_deeply(Mojo::SQL::Statement->new->parse('SELECT 1;')->to_query, {text => 'SELECT 1;', values => []}, 'semicolon'); is_deeply( Mojo::SQL::Statement->new->parse('SELECT ?;', 1)->to_query, {text => 'SELECT $1;', values => [1]}, 'one placeholder' ); is_deeply( Mojo::SQL::Statement->new->parse('SELECT ?, ?, ?;', 1, '2', [3])->to_query, {text => 'SELECT $1, $2, $3;', values => [1, '2', [3]]}, 'three placeholders' ); is_deeply( Mojo::SQL::Statement->new->parse('SELECT ??, ?;', 1)->to_query, {text => 'SELECT ?, $1;', values => [1]}, 'escaped question mark' ); my $partial = Mojo::SQL::Statement->new->parse('AND two = ? AND three = ?', 'Two', 3); is_deeply(Mojo::SQL::Statement->new->parse('SELECT * FROM foo WHERE one = ? ?', 'One', $partial)->to_query, {text => 'SELECT * FROM foo WHERE one = $1 AND two = $2 AND three = $3', values => ['One', 'Two', 3]}, 'composed'); is_deeply( Mojo::SQL::Statement->new->parse('SELECT * FROM foo WHERE one = ? ? ? AND four = ?', 'One', $partial, $partial, 4) ->to_query, { text => 'SELECT * FROM foo WHERE one = $1 AND two = $2 AND three = $3 AND two = $4 AND three = $5 AND four = $6', values => ['One', 'Two', 3, 'Two', 3, 4] }, 'composed twice' ); my $empty = Mojo::SQL::Statement->new->parse(''); is_deeply( Mojo::SQL::Statement->new->parse('SELECT 1 ?', $empty)->to_query, {text => 'SELECT 1 ', values => []}, 'empty partial' ); subtest 'From unsafe string' => sub { my $unsafe = Mojo::SQL::Statement->new->parse_unsafe(q{FROM bar WHERE ? = '?'}, 'baz', 'yada'); is_deeply( Mojo::SQL::Statement->new->parse('SELECT * ? ORDER BY id', $unsafe)->to_query, {text => q{SELECT * FROM bar WHERE baz = 'yada' ORDER BY id}, values => []}, 'unsafe spliced in' ); $unsafe = Mojo::SQL::Statement->new->parse_unsafe('FROM ?? WHERE id = ?', 23); is_deeply( Mojo::SQL::Statement->new->parse('SELECT * ?', $unsafe)->to_query, {text => 'SELECT * FROM ? WHERE id = 23', values => []}, 'escaped question mark' ); }; subtest 'to_list' => sub { my @list = Mojo::SQL::Statement->new->parse('SELECT 1')->to_list; is_deeply(\@list, ['SELECT 1'], 'static'); @list = Mojo::SQL::Statement->new->parse('SELECT ?;', 1)->to_list; is_deeply(\@list, ['SELECT $1;', 1], 'one placeholder'); @list = Mojo::SQL::Statement->new->parse('SELECT ?, ?, ?;', 1, '2', [3])->to_list; is_deeply(\@list, ['SELECT $1, $2, $3;', 1, '2', [3]], 'three placeholders'); my $partial = Mojo::SQL::Statement->new->parse('AND two = ? AND three = ?', 'Two', 3); @list = Mojo::SQL::Statement->new->parse('SELECT * FROM foo WHERE one = ? ?', 'One', $partial)->to_list; is_deeply(\@list, ['SELECT * FROM foo WHERE one = $1 AND two = $2 AND three = $3', 'One', 'Two', 3], 'composed'); my $empty = Mojo::SQL::Statement->new->parse(''); @list = Mojo::SQL::Statement->new->parse('SELECT 1 ?', $empty)->to_list; is_deeply(\@list, ['SELECT 1 '], 'empty partial'); @list = Mojo::SQL::Statement->new->parse('SELECT ?, ?, ?;', 1, '2', [3])->to_list({placeholder => '?'}); is_deeply(\@list, ['SELECT ?, ?, ?;', 1, '2', [3]], 'custom placeholder'); }; subtest 'to_array' => sub { my $array = Mojo::SQL::Statement->new->parse('SELECT 1')->to_array; is_deeply($array, ['SELECT 1'], 'static'); $array = Mojo::SQL::Statement->new->parse('SELECT ?;', 1)->to_array; is_deeply($array, ['SELECT $1;', 1], 'one placeholder'); $array = Mojo::SQL::Statement->new->parse('SELECT ?, ?, ?;', 1, '2', [3])->to_array; is_deeply($array, ['SELECT $1, $2, $3;', 1, '2', [3]], 'three placeholders'); my $partial = Mojo::SQL::Statement->new->parse('AND two = ? AND three = ?', 'Two', 3); $array = Mojo::SQL::Statement->new->parse('SELECT * FROM foo WHERE one = ? ?', 'One', $partial)->to_array; is_deeply($array, ['SELECT * FROM foo WHERE one = $1 AND two = $2 AND three = $3', 'One', 'Two', 3], 'composed'); my $empty = Mojo::SQL::Statement->new->parse(''); $array = Mojo::SQL::Statement->new->parse('SELECT 1 ?', $empty)->to_array; is_deeply($array, ['SELECT 1 '], 'empty partial'); $array = Mojo::SQL::Statement->new->parse('SELECT ?, ?, ?;', 1, '2', [3])->to_array({placeholder => '?'}); is_deeply($array, ['SELECT ?, ?, ?;', 1, '2', [3]], 'custom placeholder'); }; }; subtest 'Functions' => sub { is_deeply sql('SELECT 1')->to_query, {text => 'SELECT 1', values => []}, 'static'; is_deeply sql('SELECT 1;')->to_query, {text => 'SELECT 1;', values => []}, 'semicolon'; is_deeply sql('SELECT ?;', 1)->to_query, {text => 'SELECT $1;', values => [1]}, 'one placeholder'; is_deeply sql('SELECT ?, ?, ?;', 1, '2', [3])->to_query, {text => 'SELECT $1, $2, $3;', values => [1, '2', [3]]}, 'three placeholders'; is_deeply sql('SELECT ??, ?;', 1)->to_query, {text => 'SELECT ?, $1;', values => [1]}, 'escaped question mark'; my $partial = sql 'AND two = ? AND three = ?', 'Two', 3; is_deeply sql('SELECT * FROM foo WHERE one = ? ?', 'One', $partial)->to_query, {text => 'SELECT * FROM foo WHERE one = $1 AND two = $2 AND three = $3', values => ['One', 'Two', 3]}, 'composed'; is_deeply sql('SELECT * FROM foo WHERE one = ? ? ? AND four = ?', 'One', $partial, $partial, 4)->to_query, { text => 'SELECT * FROM foo WHERE one = $1 AND two = $2 AND three = $3 AND two = $4 AND three = $5 AND four = $6', values => ['One', 'Two', 3, 'Two', 3, 4] }, 'composed twice'; my $empty = sql ''; is_deeply sql('SELECT 1 ?', $empty)->to_query, {text => 'SELECT 1 ', values => []}, 'empty partial'; subtest 'From unsafe string' => sub { my $unsafe = sql_unsafe q{FROM bar WHERE ? = '?'}, 'baz', 'yada'; is_deeply sql('SELECT * ? ORDER BY id', $unsafe)->to_query, {text => q{SELECT * FROM bar WHERE baz = 'yada' ORDER BY id}, values => []}, 'unsafe spliced in'; $unsafe = sql_unsafe 'FROM ?? WHERE id = ?', 23; is_deeply sql('SELECT * ?', $unsafe)->to_query, {text => 'SELECT * FROM ? WHERE id = 23', values => []}, 'escaped question mark'; }; }; subtest 'Custom placeholder' => sub { is_deeply sql('SELECT 1')->to_query({placeholder => '?'}), {text => 'SELECT 1', values => []}, 'static'; is_deeply sql('SELECT ?;', 1)->to_query({placeholder => '?'}), {text => 'SELECT ?;', values => [1]}, 'one placeholder'; is_deeply sql('SELECT ?, ?, ?;', 1, '2', [3])->to_query({placeholder => '?'}), {text => 'SELECT ?, ?, ?;', values => [1, '2', [3]]}, 'three placeholders'; my $partial = sql 'AND two = ? AND three = ?', 'Two', 3; is_deeply sql('SELECT * FROM foo WHERE one = ? ?', 'One', $partial)->to_query({placeholder => '?'}), {text => 'SELECT * FROM foo WHERE one = ? AND two = ? AND three = ?', values => ['One', 'Two', 3]}, 'composed'; is_deeply sql('SELECT * FROM foo WHERE one = ? ? ? AND four = ?', 'One', $partial, $partial, 4) ->to_query({placeholder => '?'}), { text => 'SELECT * FROM foo WHERE one = ? AND two = ? AND three = ? AND two = ? AND three = ? AND four = ?', values => ['One', 'Two', 3, 'Two', 3, 4] }, 'composed twice'; }; done_testing; Mojo-SQL-0.02/t/util.t0000644000076500000240000000270215200323441013054 0ustar sristaffuse Mojo::Base -strict, -signatures; use Test::More; use Mojo::SQL qw(escape_identifier escape_literal); subtest 'escape_identifier' => sub { is escape_identifier(''), '""', 'empty string'; is escape_identifier('0'), '"0"', 'zero'; is escape_identifier("Ain't misbehaving "), q{"Ain't misbehaving "}, 'apostrophe'; is escape_identifier('NULL'), '"NULL"', 'NULL'; is escape_identifier('some"identifier'), '"some""identifier"', 'embedded double quote'; is escape_identifier(23), '"23"', 'number'; }; subtest 'escape_literal' => sub { is escape_literal(''), "''", 'empty string'; is escape_literal('0'), "'0'", 'zero'; is escape_literal("Ain't misbehaving "), "'Ain''t misbehaving '", 'apostrophe'; is escape_literal('NULL'), "'NULL'", 'NULL'; is escape_literal('some"identifier'), q{'some"identifier'}, 'embedded double quote'; is escape_literal(qq{backslash \\all' \the things}), qq{ E'backslash \\\\all'' \the things'}, 'backslash'; is escape_literal(23), "'23'", 'number'; }; done_testing; Mojo-SQL-0.02/t/pod_coverage.t0000644000076500000240000000044615200334254014543 0ustar sristaffuse Mojo::Base -strict; use Test::More; plan skip_all => 'set TEST_POD to enable this test (developer only!)' unless $ENV{TEST_POD} || $ENV{TEST_ALL}; plan skip_all => 'Test::Pod::Coverage 1.04+ required for this test!' unless eval 'use Test::Pod::Coverage 1.04; 1'; all_pod_coverage_ok(); Mojo-SQL-0.02/README.md0000644000076500000240000000452715200732720012741 0ustar sristaff # Mojo::SQL Safely generate and compose SQL statements from [Perl](https://perl.org). ```perl use Mojo::SQL qw(sql); # {text => 'SELECT * FROM users WHERE name = $1', values => ['sebastian']} my $query = sql('SELECT * FROM users WHERE name = ?', 'sebastian')->to_query; ``` To prevent SQL injection attacks, every `?` in the input becomes a placeholder in the generated query, with the corresponding value bound to it. Partial statements can even be used recursively to build more complex queries. Literal question marks can be escaped with `??`. ```perl # {text => 'SELECT ? AS literal, $1 AS bound', values => ['value']} my $query = sql('SELECT ?? AS literal, ? AS bound', 'value')->to_query; ``` ```perl my $role = 'admin'; my $partial = sql('AND role = ?', $role); my $name = 'root'; # {text => 'SELECT * FROM users WHERE name = $1 AND role = $2', values => ['root', 'admin']} my $query = sql('SELECT * FROM users WHERE name = ? ?', $name, $partial)->to_query; ``` Make partial statements optional to dynamically generate `WHERE` clauses. ```perl my $optional = $foo ? sql('AND foo IS NOT NULL') : sql(''); my $query = sql('SELECT * FROM users WHERE name = ? ?', 'sebastian', $optional)->to_query; ``` And if you need a little more control over the generated SQL query, you can also bypass safety features with `sql_unsafe`. But make sure to handle unsafe values yourself with appropriate escaping functions for your database. For PostgreSQL there are `escape_literal` and `escape_identifier` functions included with this module. ```perl use Mojo::SQL qw(sql sql_unsafe escape_literal); my $role = 'role = ' . escape_literal('power user'); my $partial = sql_unsafe('AND ?', $role); my $name = 'root'; # {text => "SELECT * FROM users WHERE name = $1 AND role = 'power user'", values => ['root']} my $query = sql('SELECT * FROM users WHERE name = ? ?', $name, $partial)->to_query; ``` For databases that do not support numbered placeholders like `$1` and `$2`, you can set a custom character with the `placeholder` option. ```perl # {text => 'SELECT * FROM users WHERE name = ?', values => ['root']} my $query = sql('SELECT * FROM users WHERE name = ?', 'root')->to_query({placeholder => '?'}); ``` ## Installation All you need is Perl 5.20 or newer. $ cpanm -n Mojo::SQL We recommend the use of a [Perlbrew](http://perlbrew.pl) environment. Mojo-SQL-0.02/META.yml0000644000076500000240000000161215200733313012722 0ustar sristaff--- abstract: 'Safely generate and compose SQL statements' author: - 'Sebastian Riedel ' build_requires: ExtUtils::MakeMaker: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'ExtUtils::MakeMaker version 7.76, CPAN::Meta::Converter version 2.150010' license: mit meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Mojo-SQL no_index: directory: - t - inc - examples - t requires: Mojolicious: '9.41' perl: '5.020' resources: IRC: url: irc://irc.libera.chat/#mojo web: https://web.libera.chat/#mojo bugtracker: https://github.com/mojolicious/mojo-sql/issues homepage: https://mojolicious.org license: http://www.opensource.org/licenses/mit repository: https://github.com/mojolicious/mojo-sql.git version: '0.02' x_serialization_backend: 'CPAN::Meta::YAML version 0.020' Mojo-SQL-0.02/lib/0000755000076500000240000000000015200733313012217 5ustar sristaffMojo-SQL-0.02/lib/Mojo/0000755000076500000240000000000015200733313013123 5ustar sristaffMojo-SQL-0.02/lib/Mojo/SQL.pm0000644000076500000240000001022115200733040014111 0ustar sristaffpackage Mojo::SQL; use Mojo::Base 'Exporter', -signatures; use Mojo::SQL::Statement; our $VERSION = '0.02'; our @EXPORT_OK = qw(escape_identifier escape_literal sql sql_unsafe); sub escape_identifier ($identifier) { my $string = "$identifier"; $string =~ s/"/""/g; return qq{"$string"}; } sub escape_literal ($literal) { my $string = "$literal"; my $escape = $string =~ /\\/ ? 1 : 0; $string =~ s/\\/\\\\/g; $string =~ s/'/''/g; return $escape ? qq{ E'$string'} : qq{'$string'}; } sub sql ($text, @values) { Mojo::SQL::Statement->new->parse($text, @values) } sub sql_unsafe ($text, @values) { Mojo::SQL::Statement->new->parse_unsafe($text, @values) } 1; =encoding utf8 =head1 NAME Mojo::SQL - Safely generate and compose SQL statements =head1 SYNOPSIS use Mojo::SQL qw(sql); # {text => 'SELECT * FROM users WHERE name = $1', values => ['sebastian']} my $query = sql('SELECT * FROM users WHERE name = ?', 'sebastian')->to_query; =head1 DESCRIPTION L safely generates and composes SQL statements. To prevent SQL injection attacks, every C in the input becomes a placeholder in the generated query, with the corresponding value bound to it. Partial statements can be composed recursively to build more complex queries. Literal question marks can be escaped with C. use Mojo::SQL qw(sql); my $role = 'admin'; my $partial = sql('AND role = ?', $role); my $name = 'root'; # {text => 'SELECT * FROM users WHERE name = $1 AND role = $2', values => ['root', 'admin']} my $query = sql('SELECT * FROM users WHERE name = ? ?', $name, $partial)->to_query; Make partial statements optional to dynamically generate C clauses. my $optional = $foo ? sql('AND foo IS NOT NULL') : sql(''); my $query = sql('SELECT * FROM users WHERE name = ? ?', 'sebastian', $optional)->to_query; If you need a little more control over the generated SQL query, you can also bypass safety features with L. But make sure to handle unsafe values yourself with appropriate escaping functions for your database. For PostgreSQL there are L and L functions included with this module. use Mojo::SQL qw(sql sql_unsafe escape_literal); my $role = 'role = ' . escape_literal('power user'); my $partial = sql_unsafe 'AND ?', $role; my $name = 'root'; # {text => "SELECT * FROM users WHERE name = \$1 AND role = 'power user'", values => ['root']} my $query = sql('SELECT * FROM users WHERE name = ? ?', $name, $partial)->to_query; For databases that do not support numbered placeholders like C<$1> and C<$2>, you can set a custom character with the C option. # {text => 'SELECT * FROM users WHERE name = ?', values => ['root']} my $query = sql('SELECT * FROM users WHERE name = ?', 'root')->to_query({placeholder => '?'}); =head1 FUNCTIONS L implements the following functions, which can be imported individually. =head2 escape_identifier my $escaped = escape_identifier('some_table'); Escape an identifier (only the PostgreSQL format is currently supported). =head2 escape_literal my $escaped = escape_literal('some value'); Escape a literal (only the PostgreSQL format is currently supported). =head2 sql my $stmt = sql('SELECT * FROM users WHERE name = ?', 'sebastian'); Create a new L from an SQL string. Each C in the string becomes a placeholder, and the corresponding value is bound to it. L values are spliced in recursively, so partial statements can be composed to build more complex queries. Literal question marks can be escaped with C. =head2 sql_unsafe my $stmt = sql_unsafe 'SELECT * FROM users WHERE name = ?', 'sebastian'; Create a new L without safe placeholders. Each C in the string is replaced literally by the corresponding value. Literal question marks can be escaped with C. Use with care. =head1 COPYRIGHT AND LICENSE Copyright (C) 2026, Sebastian Riedel. This program is free software, you can redistribute it and/or modify it under the terms of the MIT license. =head1 SEE ALSO L, L, L. =cut Mojo-SQL-0.02/lib/Mojo/SQL/0000755000076500000240000000000015200733313013562 5ustar sristaffMojo-SQL-0.02/lib/Mojo/SQL/Statement.pm0000644000076500000240000001176115200733006016071 0ustar sristaffpackage Mojo::SQL::Statement; use Mojo::Base -base, -signatures; use Scalar::Util qw(blessed); has [qw(parts values)] => sub { [] }; sub parse ($self, $text, @values) { my $escape = "\0"; $escape .= "\0" while index($text, $escape) >= 0; $text =~ s/\?\?/$escape/g; my @text_parts = split /\?/, $text, -1; @text_parts = ('') unless @text_parts; s/\Q$escape\E/?/g for @text_parts; my (@merged_parts, @merged_values); my $merge_next = 0; for my $i (0 .. $#text_parts) { if ($merge_next) { $merged_parts[-1] .= $text_parts[$i]; $merge_next = 0; } else { push @merged_parts, $text_parts[$i] } next if $i == $#text_parts; my $value = $values[$i]; if (blessed($value) && $value->isa('Mojo::SQL::Statement')) { my @value_parts = @{$value->parts}; $merged_parts[-1] .= shift @value_parts; push @merged_parts, @value_parts; push @merged_values, @{$value->values}; $merge_next = 1; } else { push @merged_values, $value } } $self->{parts} = \@merged_parts; $self->{values} = \@merged_values; return $self; } sub parse_unsafe ($self, $text, @values) { my $escape = "\0"; $escape .= "\0" while index($text, $escape) >= 0; $text =~ s/\?\?/$escape/g; my @text_parts = split /\?/, $text, -1; s/\Q$escape\E/?/g for @text_parts; my @merged; for my $i (0 .. $#text_parts) { push @merged, $text_parts[$i]; push @merged, $values[$i] if $i < $#text_parts; } $self->{parts} = [join '', @merged]; $self->{values} = []; return $self; } sub to_query ($self, $options = {}) { {text => $self->to_string($options), values => $self->values} } sub to_array ($self, $options = {}) { [$self->to_string($options), @{$self->values}] } sub to_list ($self, $options = {}) { @{$self->to_array($options)} } sub to_string ($self, $options = {}) { my @query; my $placeholder = $options->{placeholder}; my $parts = $self->parts; for my $i (1 .. scalar @$parts) { push @query, $parts->[$i - 1]; push @query, defined $placeholder ? $placeholder : "\$$i" if defined $parts->[$i]; } return join '', @query; } 1; =encoding utf8 =head1 NAME Mojo::SQL::Statement - SQL statement container =head1 SYNOPSIS use Mojo::SQL::Statement; my $stmt = Mojo::SQL::Statement->new->parse('SELECT * FROM users WHERE name = ?', 'sebastian'); my $query = $stmt->to_query; =head1 DESCRIPTION L is a container for an SQL statement and its bind values. Statements are composable by passing one as a value to another, in which case its parts and values are spliced in recursively. =head1 ATTRIBUTES L implements the following attributes. =head2 parts my $parts = $stmt->parts; $stmt = $stmt->parts(['SELECT * FROM users WHERE name = ', '']); The literal SQL fragments around each placeholder, as an array reference. There is always one more fragment than placeholder. =head2 values my $values = $stmt->values; $stmt = $stmt->values(['sebastian']); The bind values for each placeholder, as an array reference. =head1 METHODS L inherits all methods from L and implements the following new ones. =head2 parse $stmt = $stmt->parse('SELECT * FROM users WHERE name = ?', 'sebastian'); Parse an SQL string with C placeholders and bind values into L and L. L values are spliced in recursively, allowing partial statements to be composed. Literal question marks can be escaped with C. =head2 parse_unsafe $stmt = $stmt->parse_unsafe("AND role = 'admin'"); $stmt = $stmt->parse_unsafe('AND ?', "role = 'admin'"); Parse an SQL string where every C slot is replaced literally by the corresponding value. The result has no placeholders or bind values; use with care, and make sure to escape values yourself with the appropriate escaping functions for your database. Literal question marks can be escaped with C. =head2 to_array my $array = $stmt->to_array; my $array = $stmt->to_array({placeholder => '?'}); Render the statement to an array reference containing the SQL text and bind values, ready to be passed to a database driver. Accepts the same options as L. =head2 to_list my @list = $stmt->to_list; my @list = $stmt->to_list({placeholder => '?'}); Same as L but returns a list. =head2 to_query my $query = $stmt->to_query; my $query = $stmt->to_query({placeholder => '?'}); Render the statement to a query hash reference with C and C keys, ready to be passed to a database driver. These options are currently available: =over 2 =item placeholder placeholder => '?' Placeholder character to use, defaults to numbered placeholders like C<$1> and C<$2>. =back =head2 to_string my $string = $stmt->to_string; my $string = $stmt->to_string({placeholder => '?'}); Render just the SQL string portion of the statement. Accepts the same options as L. =head1 SEE ALSO L, L, L. =cut Mojo-SQL-0.02/Makefile.PL0000644000076500000240000000207715200323441013426 0ustar sristaffuse 5.020; use strict; use warnings; use utf8; use ExtUtils::MakeMaker; WriteMakefile( NAME => 'Mojo::SQL', VERSION_FROM => 'lib/Mojo/SQL.pm', ABSTRACT => 'Safely generate and compose SQL statements', AUTHOR => 'Sebastian Riedel ', LICENSE => 'mit', META_MERGE => { dynamic_config => 0, 'meta-spec' => {version => 2}, no_index => {directory => ['examples', 't']}, prereqs => {runtime => {requires => {perl => '5.020'}}}, resources => { bugtracker => {web => 'https://github.com/mojolicious/mojo-sql/issues'}, homepage => 'https://mojolicious.org', license => ['http://www.opensource.org/licenses/mit'], repository => { type => 'git', url => 'https://github.com/mojolicious/mojo-sql.git', web => 'https://github.com/mojolicious/mojo-sql', }, x_IRC => {url => 'irc://irc.libera.chat/#mojo', web => 'https://web.libera.chat/#mojo'} }, }, PREREQ_PM => {Mojolicious => '9.41'}, test => {TESTS => 't/*.t'} ); Mojo-SQL-0.02/.perltidyrc0000644000076500000240000000102415200323441013625 0ustar sristaff-pbp # Start with Perl Best Practices -w # Show all warnings -iob # Ignore old breakpoints -l=120 # 120 characters per line -mbl=2 # No more than 2 blank lines -i=2 # Indentation is 2 columns -ci=2 # Continuation indentation is 2 columns -vt=0 # Less vertical tightness -pt=2 # High parenthesis tightness -bt=2 # High brace tightness -sbt=2 # High square bracket tightness -wn # Weld nested containers -isbc # Don't indent comments without leading space -nst # Don't output to STDOUT Mojo-SQL-0.02/META.json0000644000076500000240000000302415200733313013071 0ustar sristaff{ "abstract" : "Safely generate and compose SQL statements", "author" : [ "Sebastian Riedel " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.76, CPAN::Meta::Converter version 2.150010", "license" : [ "mit" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Mojo-SQL", "no_index" : { "directory" : [ "t", "inc", "examples", "t" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Mojolicious" : "9.41", "perl" : "5.020" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/mojolicious/mojo-sql/issues" }, "homepage" : "https://mojolicious.org", "license" : [ "http://www.opensource.org/licenses/mit" ], "repository" : { "type" : "git", "url" : "https://github.com/mojolicious/mojo-sql.git", "web" : "https://github.com/mojolicious/mojo-sql" }, "x_IRC" : { "url" : "irc://irc.libera.chat/#mojo", "web" : "https://web.libera.chat/#mojo" } }, "version" : "0.02", "x_serialization_backend" : "JSON::PP version 4.16" }