Lines 1-6
Link Here
|
1 |
package Koha::OAI::Server::ListBase; |
1 |
package Koha::OAI::Server::ListBase; |
2 |
|
2 |
|
3 |
# Copyright The National Library of Finland, University of Helsinki 2016-2017 |
3 |
# Copyright The National Library of Finland, University of Helsinki 2016-2018 |
4 |
# |
4 |
# |
5 |
# This file is part of Koha. |
5 |
# This file is part of Koha. |
6 |
# |
6 |
# |
Lines 46-181
sub GetRecords {
Link Here
|
46 |
$set = GetOAISetBySpec($token->{'set'}); |
46 |
$set = GetOAISetBySpec($token->{'set'}); |
47 |
} |
47 |
} |
48 |
my $offset = $token->{offset}; |
48 |
my $offset = $token->{offset}; |
49 |
my $deleted = defined $token->{deleted} ? $token->{deleted} : 0; |
|
|
50 |
my $deleted_count = defined $token->{deleted_count} ? $token->{deleted_count} : 0; |
51 |
my $max = $repository->{koha_max_count}; |
49 |
my $max = $repository->{koha_max_count}; |
52 |
my $count = 0; |
50 |
my $count = 0; |
53 |
my $format = $args{metadataPrefix} || $token->{metadata_prefix}; |
51 |
my $format = $args{metadataPrefix} || $token->{metadata_prefix}; |
54 |
my $include_items = $repository->items_included( $format ); |
52 |
my $include_items = $repository->items_included( $format ); |
55 |
|
53 |
|
56 |
# Since creating a union of normal and deleted record tables would be a heavy |
54 |
my $sql = " |
57 |
# operation in a large database, build results in two stages: |
55 |
SELECT biblionumber, deleted_at |
58 |
# first deleted records ($deleted == 1), then normal records ($deleted == 0) |
56 |
FROM biblio_metadata |
59 |
STAGELOOP: |
57 |
WHERE (timestamp >= ? AND timestamp <= ?) |
60 |
for ( ; $deleted >= 0; $deleted-- ) { |
58 |
"; |
61 |
my $table = $deleted ? 'deletedbiblio_metadata' : 'biblio_metadata'; |
59 |
my @bind_params = ($token->{'from_arg'}, $token->{'until_arg'}); |
62 |
my $sql = " |
|
|
63 |
SELECT biblionumber |
64 |
FROM $table |
65 |
WHERE (timestamp >= ? AND timestamp <= ?) |
66 |
"; |
67 |
my @bind_params = ($token->{'from_arg'}, $token->{'until_arg'}); |
68 |
|
69 |
if ($include_items) { |
70 |
$sql .= " |
71 |
OR biblionumber IN (SELECT biblionumber from items WHERE timestamp >= ? AND timestamp <= ? AND deleted_at IS NOT NULL) |
72 |
"; |
73 |
push @bind_params, ($token->{'from_arg'}, $token->{'until_arg'}); |
74 |
if (!$deleted) { |
75 |
$sql .= " |
76 |
OR biblionumber IN (SELECT biblionumber from items WHERE timestamp >= ? AND timestamp <= ? AND deleted_at IS NULL) |
77 |
"; |
78 |
push @bind_params, ($token->{'from_arg'}, $token->{'until_arg'}); |
79 |
} |
80 |
} |
81 |
|
60 |
|
|
|
61 |
if ($include_items) { |
82 |
$sql .= " |
62 |
$sql .= " |
83 |
ORDER BY biblionumber |
63 |
OR biblionumber IN (SELECT biblionumber from items WHERE timestamp >= ? AND timestamp <= ?) |
84 |
"; |
64 |
"; |
|
|
65 |
push @bind_params, ($token->{'from_arg'}, $token->{'until_arg'}); |
66 |
} |
85 |
|
67 |
|
86 |
# Use a subquery for sets since it allows us to use an index in |
68 |
$sql .= " |
87 |
# biblioitems table and is quite a bit faster than a join. |
69 |
ORDER BY biblionumber |
88 |
if (defined $set) { |
70 |
"; |
89 |
$sql = " |
|
|
90 |
SELECT bi.* FROM ($sql) bi |
91 |
WHERE bi.biblionumber in (SELECT osb.biblionumber FROM oai_sets_biblios osb WHERE osb.set_id = ?) |
92 |
"; |
93 |
push @bind_params, $set->{'id'}; |
94 |
} |
95 |
|
71 |
|
96 |
$sql .= " |
72 |
# Use a subquery for sets since it allows us to use an index in |
97 |
LIMIT " . ($max + 1) . " |
73 |
# biblioitems table and is quite a bit faster than a join. |
98 |
OFFSET " . ($offset - $deleted_count); |
74 |
if (defined $set) { |
99 |
|
75 |
$sql = " |
100 |
my $sth = $dbh->prepare( $sql ) || die( 'Could not prepare statement: ' . $dbh->errstr ); |
76 |
SELECT bi.* FROM ($sql) bi |
101 |
|
77 |
WHERE bi.biblionumber in (SELECT osb.biblionumber FROM oai_sets_biblios osb WHERE osb.set_id = ?) |
102 |
if ( $deleted ) { |
78 |
"; |
103 |
$sql = " |
79 |
push @bind_params, $set->{'id'}; |
104 |
SELECT MAX(timestamp) |
80 |
} |
105 |
FROM ( |
81 |
|
106 |
SELECT timestamp FROM deletedbiblio_metadata WHERE biblionumber = ? |
82 |
$sql .= " |
107 |
UNION |
83 |
LIMIT " . ($max + 1) . " |
108 |
SELECT timestamp FROM items WHERE biblionumber = ? AND deleted_at IS NOT NULL |
84 |
OFFSET $offset"; |
109 |
) bis |
85 |
|
110 |
"; |
86 |
my $sth = $dbh->prepare( $sql ) || die( 'Could not prepare statement: ' . $dbh->errstr ); |
111 |
} else { |
87 |
|
112 |
$sql = " |
88 |
$sql = " |
113 |
SELECT MAX(timestamp) |
89 |
SELECT MAX(timestamp) |
114 |
FROM ( |
90 |
FROM ( |
115 |
SELECT timestamp FROM biblio_metadata WHERE biblionumber = ? |
91 |
SELECT timestamp FROM biblio_metadata WHERE biblionumber = ? |
116 |
UNION |
92 |
UNION |
117 |
SELECT timestamp FROM items WHERE biblionumber = ? AND deleted_at IS NULL |
93 |
SELECT timestamp FROM items WHERE biblionumber = ? |
118 |
UNION |
94 |
) bi |
119 |
SELECT timestamp FROM items WHERE biblionumber = ? AND deleted_at IS NOT NULL |
95 |
"; |
120 |
) bi |
96 |
my $record_sth = $dbh->prepare( $sql ) || die( 'Could not prepare statement: ' . $dbh->errstr ); |
121 |
"; |
97 |
|
|
|
98 |
$sth->execute( @bind_params ) || die( 'Could not execute statement: ' . $sth->errstr ); |
99 |
while ( my ($biblionumber, $deleted_at) = $sth->fetchrow ) { |
100 |
$count++; |
101 |
if ( $count > $max ) { |
102 |
$self->resumptionToken( |
103 |
new Koha::OAI::Server::ResumptionToken( |
104 |
metadataPrefix => $token->{metadata_prefix}, |
105 |
from => $token->{from}, |
106 |
until => $token->{until}, |
107 |
offset => $token->{offset} + $max, |
108 |
set => $token->{set}, |
109 |
) |
110 |
); |
111 |
last; |
122 |
} |
112 |
} |
123 |
my $record_sth = $dbh->prepare( $sql ) || die( 'Could not prepare statement: ' . $dbh->errstr ); |
113 |
$record_sth->execute( ( $biblionumber, $biblionumber ) ) || die( 'Could not execute statement: ' . $sth->errstr ); |
124 |
|
|
|
125 |
$sth->execute( @bind_params ) || die( 'Could not execute statement: ' . $sth->errstr ); |
126 |
while ( my ($biblionumber) = $sth->fetchrow ) { |
127 |
$count++; |
128 |
if ( $count > $max ) { |
129 |
$self->resumptionToken( |
130 |
new Koha::OAI::Server::ResumptionToken( |
131 |
metadataPrefix => $token->{metadata_prefix}, |
132 |
from => $token->{from}, |
133 |
until => $token->{until}, |
134 |
offset => $token->{offset} + $max, |
135 |
set => $token->{set}, |
136 |
deleted => $deleted, |
137 |
deleted_count => $deleted_count |
138 |
) |
139 |
); |
140 |
last STAGELOOP; |
141 |
} |
142 |
my @params = $deleted ? ( $biblionumber, $biblionumber ) : ( $biblionumber, $biblionumber, $biblionumber ); |
143 |
$record_sth->execute( @params ) || die( 'Could not execute statement: ' . $sth->errstr ); |
144 |
|
114 |
|
145 |
my ($timestamp) = $record_sth->fetchrow; |
115 |
my ($timestamp) = $record_sth->fetchrow; |
146 |
|
116 |
|
147 |
my $oai_sets = GetOAISetsBiblio($biblionumber); |
117 |
my $oai_sets = GetOAISetsBiblio($biblionumber); |
148 |
my @setSpecs; |
118 |
my @setSpecs; |
149 |
foreach ( @$oai_sets ) { |
119 |
foreach ( @$oai_sets ) { |
150 |
push @setSpecs, $_->{spec}; |
120 |
push @setSpecs, $_->{spec}; |
151 |
} |
121 |
} |
152 |
if ( $metadata ) { |
122 |
if ( $metadata ) { |
153 |
my $marcxml = !$deleted ? $repository->get_biblio_marcxml($biblionumber, $format) : undef; |
123 |
my $marcxml = !$deleted_at ? $repository->get_biblio_marcxml($biblionumber, $format) : undef; |
154 |
if ( $marcxml ) { |
124 |
if ( $marcxml ) { |
155 |
$self->record( Koha::OAI::Server::Record->new( |
125 |
$self->record( Koha::OAI::Server::Record->new( |
156 |
$repository, $marcxml, $timestamp, \@setSpecs, |
126 |
$repository, $marcxml, $timestamp, \@setSpecs, |
157 |
identifier => $repository->{ koha_identifier } . ':' . $biblionumber, |
127 |
identifier => $repository->{ koha_identifier } . ':' . $biblionumber, |
158 |
metadataPrefix => $token->{metadata_prefix} |
128 |
metadataPrefix => $token->{metadata_prefix} |
159 |
) ); |
129 |
) ); |
160 |
} else { |
|
|
161 |
$self->record( Koha::OAI::Server::DeletedRecord->new( |
162 |
$timestamp, \@setSpecs, identifier => $repository->{ koha_identifier } . ':' . $biblionumber |
163 |
) ); |
164 |
} |
165 |
} else { |
130 |
} else { |
166 |
$timestamp =~ s/ /T/; |
131 |
$self->record( Koha::OAI::Server::DeletedRecord->new( |
167 |
$timestamp .= 'Z'; |
132 |
$timestamp, \@setSpecs, identifier => $repository->{ koha_identifier } . ':' . $biblionumber |
168 |
$self->identifier( new HTTP::OAI::Header( |
|
|
169 |
identifier => $repository->{ koha_identifier} . ':' . $biblionumber, |
170 |
datestamp => $timestamp, |
171 |
status => $deleted ? 'deleted' : undef |
172 |
) ); |
133 |
) ); |
173 |
} |
134 |
} |
|
|
135 |
} else { |
136 |
$timestamp =~ s/ /T/; |
137 |
$timestamp .= 'Z'; |
138 |
$self->identifier( new HTTP::OAI::Header( |
139 |
identifier => $repository->{ koha_identifier} . ':' . $biblionumber, |
140 |
datestamp => $timestamp, |
141 |
status => $deleted_at ? 'deleted' : undef |
142 |
) ); |
174 |
} |
143 |
} |
175 |
# Store offset and deleted record count |
|
|
176 |
$offset += $count; |
177 |
$deleted_count = $offset if ($deleted); |
178 |
} |
144 |
} |
|
|
145 |
# Store offset |
146 |
$offset += $count; |
179 |
return $count; |
147 |
return $count; |
180 |
} |
148 |
} |
181 |
|
149 |
|