view release on metacpan or search on metacpan
=encoding utf-8
=head1 NAME
App::AltSQL - A drop in replacement to the MySQL prompt with a pluggable Perl interface
=head1 SYNOPSIS
./altsql -h <host> -u <username> -D <database> -p<password>
altsql> select * from film limit 4;
âââââââââââ¤âââââââââââââââââââ¤ââââââââââââââââââââââââââââ
â film_id â title â description
âââââââââââªâââââââââââââââââââªââââââââââââââââââââââââââââ
â 1 â ACADEMY DINOSAUR â A Epic Drama of a Feminist
â 2 â ACE GOLDFINGER â A Astounding Epistle of a D
â 3 â ADAPTATION HOLES â A Astounding Reflection of
â 4 â AFFAIR PREJUDICE â A Fanciful Documentary of a
âââââââââââ§âââââââââââââââââââ§ââââââââââââââââââââââââââââ
lib/App/AltSQL.pm view on Meta::CPAN
package App::AltSQL;
=encoding utf-8
=head1 NAME
App::AltSQL - A drop in replacement to the MySQL prompt with a pluggable Perl interface
=head1 SYNOPSIS
./altsql -h <host> -u <username> -D <database> -p<password>
altsql> select * from film limit 4;
âââââââââââ¤âââââââââââââââââââ¤ââââââââââââââââââââââââââââ
â film_id â title â description
âââââââââââªâââââââââââââââââââªââââââââââââââââââââââââââââ
â 1 â ACADEMY DINOSAUR â A Epic Drama of a Feminist
â 2 â ACE GOLDFINGER â A Astounding Epistle of a D
â 3 â ADAPTATION HOLES â A Astounding Reflection of
â 4 â AFFAIR PREJUDICE â A Fanciful Documentary of a
âââââââââââ§âââââââââââââââââââ§ââââââââââââââââââââââââââââ
lib/App/AltSQL.pm view on Meta::CPAN
=head2 Command Line
The following options are available.
=over 4
=item -h HOSTNAME | --host HOSTNAME
=item -u USERNAME | --user USERNAME
=item -p | --password=PASSWORD | -pPASSWORD
=item --port PORT
=item -D DATABASE | --database DATABASE
Basic connection parameters to the MySQL database.
=item --A | --no-auto-rehash
By default, upon startup and whenever the database is changed, the C<information_schema> tables will be read to perform tab completion. Disable this behavior to get a faster startup time (but no tab complete).
lib/App/AltSQL.pm view on Meta::CPAN
if (my $default = $args_spec{$key}{default}) {
$args{"_${args_class}_$key"} = $default;
}
}
}
}
# Password is a special case
foreach my $i (0..$#argv) {
my $arg = $argv[$i];
next unless $arg =~ m{^(?:-p|--password=)(.*)$};
splice @argv, $i, 1;
if (length $1) {
$args{_model_password} = $1;
# Remove the password from the program name so people can't see it in process listings
$0 = join ' ', $0, @argv;
}
else {
# Prompt the user for the password
require Term::ReadKey;
Term::ReadKey::ReadMode('noecho');
print "Enter password: ";
$args{_model_password} = Term::ReadKey::ReadLine(0);
Term::ReadKey::ReadMode('normal');
print "\n";
chomp $args{_model_password};
}
last; # I've found what I was looking for
}
GetOptionsFromArray(\@argv, %opts_spec);
# Database is a special case; if left over arguments, that's the database name
if (@argv && int @argv == 1) {
$args{_model_database} = $argv[0];
}
lib/App/AltSQL/Model/MySQL.pm view on Meta::CPAN
=head1 DESCRIPTION
This module is currently the only Model supported by L<App::AltSQL>.
Upon startup, we will read in C<$HOME/.my.cnf> and will read and respect the following configuration variables:
=over 4
=item B<user>
=item B<password>
=item B<host>
=item B<port>
=item B<prompt>
=item B<safe_update>
=item B<select_limit>
lib/App/AltSQL/Model/MySQL.pm view on Meta::CPAN
require DBIx::MyParsePP;
};
if ($@) {
return 0; # when we use this we check for definedness as well as boolean
}
return DBIx::MyParsePP->new();
});
has 'dbh' => (is => 'rw');
has 'current_database' => (is => 'rw');
has [qw(host user password database port)] => ( is => 'ro' );
has [qw(no_auto_rehash select_limit safe_update prompt)] => ( is => 'ro' );
sub args_spec {
return (
host => {
cli => 'host|h=s',
help => '-h HOSTNAME | --host HOSTNAME',
},
user => {
cli => 'user|u=s',
help => '-u USERNAME | --user USERNAME',
},
password => {
help => '-p | --password=PASSWORD | -pPASSWORD',
},
database => {
cli => 'database|d=s',
help => '-d DATABASE | --database DATABASE',
},
port => {
cli => 'port=i',
help => '--port PORT',
},
no_auto_rehash => {
lib/App/AltSQL/Model/MySQL.pm view on Meta::CPAN
foreach my $path (@config_paths) {
(-e $path) or next;
$self->read_my_dot_cnf($path);
}
}
sub read_my_dot_cnf {
my $self = shift;
my $path = shift;
my @valid_keys = qw( user password host port database prompt safe_update select_limit no_auto_rehash ); # keys we'll read
my @valid_sections = qw( client mysql ); # valid [section] names
my @boolean_keys = qw( safe_update no_auto_rehash );
open MYCNF, "<$path";
# ignore lines in file until we hit a valid [section]
# then read key=value pairs
my $in_valid_section = 0;
while(<MYCNF>) {
lib/App/AltSQL/Model/MySQL.pm view on Meta::CPAN
close MYCNF;
}
sub db_connect {
my $self = shift;
my $dsn = 'DBI:mysql:' . join (';',
map { "$_=" . $self->$_ }
grep { defined $self->$_ }
qw(database host port)
);
my $dbh = DBI->connect($dsn, $self->user, $self->password, {
PrintError => 0,
mysql_auto_reconnect => 1,
mysql_enable_utf8 => 1,
}) or die $DBI::errstr . "\nDSN used: '$dsn'\n";
$self->dbh($dbh);
## Update autocomplete entries
if ($self->database) {
$self->current_database($self->database);
lib/App/AltSQL/Term/Plugin/SyntaxHighlight.pm view on Meta::CPAN
fields file first flush for foreign from full function
global grant grants group
having heap high_priority hosts hour hour_minute hour_second
identified ignore index infile inner insert insert_id into isam
join
key keys kill last_insert_id leading left limit lines load local lock logs long
low_priority
match max_rows middleint min_rows minute minute_second modify month myisam
natural no
on optimize option optionally order outer outfile
pack_keys partial password primary privileges procedure process processlist
read references reload rename replace restrict returns revoke right row rows
second select show shutdown soname sql_big_result sql_big_selects sql_big_tables sql_log_off
sql_log_update sql_low_priority_updates sql_select_limit sql_small_result sql_warnings starting
status straight_join string
table tables temporary terminated to trailing type
unique unlock unsigned update usage use using
values varbinary variables varying
where with write
year_month
zerofill
t/001_arguments.t view on Meta::CPAN
use Test::More;
use Test::Deep;
BEGIN {
use_ok 'App::AltSQL';
}
ok(App::AltSQL->parse_cli_args(), "Can call without arguments");
cmp_deeply(
App::AltSQL->parse_cli_args([ qw(-u ewaters -ptestpassword -h localhost sakila) ]),
superhashof({
_model_user => 'ewaters',
_model_password => 'testpassword',
_model_host => 'localhost',
_model_database => 'sakila',
}),
'Basic parse_cli_args',
);
cmp_deeply(
App::AltSQL->parse_cli_args([qw(--port 12345 -A --help)]),
superhashof({
_model_port => 12345,
t/002_my_cnf.t view on Meta::CPAN
}
my $app = bless {}, 'App::AltSQL';
{
my $instance = App::AltSQL::Model::MySQL->new( app => $app );
my $filename = write_config(<<ENDFILE);
[client]
user = ewaters
password = 12345
host=localhost
database = sakila
ENDFILE
$instance->read_my_dot_cnf($filename);
unbless($instance);
cmp_deeply(
$instance,
superhashof({
user => 'ewaters',
password => '12345',
host => 'localhost',
database => 'sakila',
}),
'Perfectly Simple my.cnf',
);
unlink $filename;
}
{
my $instance = App::AltSQL::Model::MySQL->new( app => $app );
my $filename = write_config(<<ENDFILE);
[client]
user = ewaters
password = 12345
host = localhost
[mysql]
database = sakila
default-character-set = utf8
prompt = \\u@\\h[\\R:\\m:\\s]>
safe-update = false
ENDFILE
$instance->read_my_dot_cnf($filename);
unbless( $instance );
cmp_deeply(
$instance,
superhashof({
user => 'ewaters',
password => '12345',
host => 'localhost',
database => 'sakila',
safe_update => 0,
prompt => '\\u@\\h[\\R:\\m:\\s]>',
}),
'Multi-section my.cnf',
);
unlink $filename;
}
{
my $instance = App::AltSQL::Model::MySQL->new( app => $app );
my $filename = write_config(<<ENDFILE);
[client]
user = ewaters
password = 12345
host = localhost
[mysql]
database = sakila
default-character-set = utf8
prompt = \\u@\\h[\\R:\\m:\\s]>
safe-update = false
ENDFILE
$instance->read_my_dot_cnf($filename);
unbless($instance);
cmp_deeply(
$instance,
superhashof({
user => 'ewaters',
password => '12345',
host => 'localhost',
database => 'sakila',
safe_update => 0,
prompt => '\\u@\\h[\\R:\\m:\\s]>',
}),
'Multi-section my.cnf',
);
unlink $filename;
}
{
my $instance = App::AltSQL::Model::MySQL->new( app => $app );
my $filename = write_config(<<ENDFILE);
[client]
user=firesun
password=password123
[mysql]
#use this to get faster startup and avoid the following message:
#Reading table information for completion of table and column names
#You can turn off this feature to get a quicker startup with -A
skip-auto-rehash
select_limit = 50
#use this to set your initial database
database = sakila
ENDFILE
$instance->read_my_dot_cnf($filename);
unbless($instance);
cmp_deeply(
$instance,
superhashof({
user => 'firesun',
password => 'password123',
database => 'sakila',
no_auto_rehash => 1,
select_limit => 50,
}),
'Comments and whitespace',
);
unlink $filename;
}
done_testing;
t/sql/sakila-schema.sql view on Meta::CPAN
CREATE TABLE staff (
staff_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
first_name VARCHAR(45) NOT NULL,
last_name VARCHAR(45) NOT NULL,
address_id SMALLINT UNSIGNED NOT NULL,
picture BLOB DEFAULT NULL,
email VARCHAR(50) DEFAULT NULL,
store_id TINYINT UNSIGNED NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
username VARCHAR(16) NOT NULL,
password VARCHAR(40) BINARY DEFAULT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (staff_id),
KEY idx_fk_store_id (store_id),
KEY idx_fk_address_id (address_id),
CONSTRAINT fk_staff_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_staff_address FOREIGN KEY (address_id) REFERENCES address (address_id) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `store`