-
Notifications
You must be signed in to change notification settings - Fork 0
/
database.pm
executable file
·200 lines (170 loc) · 4.28 KB
/
database.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/usr/bin/perl
package database;
use DBI;
use Data::Dumper;
use strict;
use warnings;
my $dbh;
dbConnect();
#print Dumper(getPersonFromCode("123456789"));
#print Dumper(getState("1000000000000"));
#flipState("5010123729981", 'IN');
# Find the current state for a given barcode
# IN: a barcode
# OUT: the state (either IN or OUT)
sub getState
{
my ($barcode) = @_;
my %person = %{getPersonFromCode($barcode)};
my $query = <<SQL;
select case when coalesce(o.timestamp, timestamp(0)) < i.timestamp then 'IN' else 'OUT' end as status
from person as p
join
(
select max(i.timestamp) as timestamp
from person_log as i
where i.action = 'IN'
and i.person_id = $person{"id"}
) as i on true
left join
(
select max(o.timestamp) as timestamp
from person_log as o
where o.action = 'OUT'
and o.person_id = $person{"id"}
) as o on true
where p.id = $person{"id"};
SQL
my %result = %{dbQuerySingleRow($query)};
return $result{"status"};
}
# Toggle a user's state
# IN: the user barcode
# OUT: none
sub flipState
{
my ($barcode, $state) = @_;
$state = getState($barcode);
my $query = <<SQL;
insert into person_log (person_id, action)
select p.id, case '$state' when 'IN' then 'OUT' else 'IN' end
from person as p
where p.barcode = '$barcode';
SQL
$dbh->do($query);
}
# Find the latest log for a given person
# IN: A person ID
# OUT: hash contain a single log row
sub getLastLogFromPersonId
{
my ($id) = @_;
$id = $dbh->quote($id);
my $query = "SELECT * FROM person_log WHERE person_id=$id ORDER BY timestamp LIMIT 1";
return dbQuerySingleRow($query);
}
# Finds a single database row giving a persons details, given a barcode.
# IN: a barcode
# OUT: hashref mapping a database fields to values for a single person row
sub getPersonFromCode
{
my ($barcode) = @_;
$barcode = $dbh->quote($barcode);
my $query = "SELECT * FROM person WHERE barcode=$barcode LIMIT 1";
return dbQuerySingleRow($query);
}
# Finds the list of all hacklab members
# IN: Nothing
# OUT: Hashref mapping barcodes to peoples names.
sub getPersonList
{
my $query = "SELECT * FROM person";
my %idToPerson = %{dbQueryManyRows($query, "id")};
my %barcodeToPerson;
for my $key (keys(%idToPerson))
{
$barcodeToPerson{$idToPerson{$key}{"barcode"}} = $idToPerson{$key}{"name"};
}
return \%barcodeToPerson;
}
# Finds the current members that are in the lab
# IN: Nothing
# OUT: Array ref storing a list of names.
sub getWhosInLab
{
my $query = <<SQL;
select p.name
from person as p
join
(
select i.person_id, max(i.timestamp) as timestamp
from person_log as i
where i.action = 'IN'
group by i.person_id
) as i on i.person_id = p.id
left join
(
select o.person_id, max(o.timestamp) as timestamp
from person_log as o
where o.action = 'OUT'
group by o.person_id
) as o on o.person_id = p.id
where coalesce(o.timestamp, timestamp(0)) < i.timestamp;
SQL
my @names;
my $result = dbQueryManyRows($query, "name");
print Dumper($result);
my %resultHash = %{$result};
for my $name (keys(%resultHash))
{
push(@names,$name);
}
return \@names;
}
# Logs out all currently logged in members
# IN: Nothing
# OUT: Nothing
sub logAllOut
{
#TODO
}
# Utility to connect to database.
# Everything is hardcoded
#
# Sets up global $dbh variable
sub dbConnect
{
my $dsn = 'dbi:mysql:bigbrother:localhost:3306'; # DB DSN
# set the user and password
my $user = 'hacklab';
my $pass = 'hacklab';
# now connect and get a database handle
$dbh = DBI->connect( $dsn, $user, $pass )
or die "Can’t connect to the DB: $DBI::errstr\n";
}
# Utility function to return many database rows
# IN: SQL query
# IN: string representing the field to use as the hash key
# OUT: hashref mapping keys to database rows
sub dbQueryManyRows
{
my ($query, $key) = @_;
# prepare the query
my $sth = $dbh->prepare($query);
# execute the query
$sth->execute();
return $sth->fetchall_hashref($key);
}
# Utility funtion to return a single database row
# IN: SQL query to execute
# OUT: hashref mapping fields to values for a single database row
sub dbQuerySingleRow
{
my ($query) = @_;
# prepare the query
my $sth = $dbh->prepare($query);
# execute the query
$sth->execute();
return $sth->fetchrow_hashref();
}
1;