148 lines
5.3 KiB
Java
148 lines
5.3 KiB
Java
package eu.dnetlib.common.mdstores.backends.sql;
|
|
|
|
import java.sql.Timestamp;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.stream.Stream;
|
|
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
import org.springframework.jdbc.core.RowMapper;
|
|
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
|
|
|
import eu.dnetlib.common.mdstores.MDStoreBackend;
|
|
import eu.dnetlib.domain.mdstore.MDStore;
|
|
import eu.dnetlib.domain.mdstore.MDStoreVersion;
|
|
import eu.dnetlib.domain.mdstore.records.MetadataRecord;
|
|
import eu.dnetlib.domain.mdstore.records.MetadataRecord.MetadataRecordEncoding;
|
|
import eu.dnetlib.domain.mdstore.records.Provenance;
|
|
import eu.dnetlib.errors.MDStoreManagerException;
|
|
import jakarta.transaction.Transactional;
|
|
|
|
public class MDStoreSqlBackend implements MDStoreBackend {
|
|
|
|
private final JdbcTemplate jdbcTemplate;
|
|
|
|
private final String databaseUrl;
|
|
|
|
public MDStoreSqlBackend(final String url, final String username, final String password) {
|
|
final DriverManagerDataSource ds = new DriverManagerDataSource();
|
|
ds.setUrl(url);
|
|
ds.setUsername(username);
|
|
ds.setPassword(password);
|
|
|
|
this.jdbcTemplate = new JdbcTemplate(ds, true);
|
|
this.databaseUrl = url;
|
|
}
|
|
|
|
@Override
|
|
public void completeNewMDStore(final MDStore mdstore) {
|
|
mdstore.getParams().put("databaseUrl", this.databaseUrl);
|
|
}
|
|
|
|
@Override
|
|
public void completeNewMDStoreVersion(final MDStoreVersion version) {
|
|
version.getParams().put("databaseUrl", this.databaseUrl);
|
|
version.getParams().put("table", asTableName(version.getId()));
|
|
}
|
|
|
|
@Override
|
|
public void delete(final MDStore mdstore) throws MDStoreManagerException {
|
|
|
|
final String table = asTableName(mdstore.getId());
|
|
final String vCond = table + "-" + "%";
|
|
|
|
final List<String> toDelete =
|
|
this.jdbcTemplate.queryForList("select tablename FROM pg_tables WHERE tablename = ? OR tablename like ?", String.class, table, vCond);
|
|
|
|
toDelete.forEach(t -> this.jdbcTemplate.execute("drop table if exists " + t));
|
|
}
|
|
|
|
@Override
|
|
public void delete(final MDStoreVersion version) throws MDStoreManagerException {
|
|
this.jdbcTemplate.execute("drop table if exists " + asTableName(version.getId()));
|
|
}
|
|
|
|
@Override
|
|
public List<MetadataRecord> listEntries(final MDStoreVersion version, final long limit) throws MDStoreManagerException {
|
|
return this.jdbcTemplate.query("select * from " + asTableName(version.getId()) + " limit ?", mdstoreMapper(), limit);
|
|
}
|
|
|
|
@Override
|
|
@Transactional
|
|
public void saveRecords(final MDStoreVersion version, final Stream<MetadataRecord> inputStream) {
|
|
final String table = asTableName(version.getId());
|
|
|
|
createTableIfMissing(table);
|
|
|
|
final String sql = "insert into " + table + " " +
|
|
"(id, originalid, body, dsid, dsname, dsprefix, dateofcollection, dateoftransformation) " +
|
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?) " +
|
|
"ON CONFLICT (id) DO UPDATE SET " +
|
|
"(originalid, body, dsid, dsname, dsprefix, dateofcollection, dateoftransformation) = " +
|
|
"(EXCLUDED.originalid, EXCLUDED.body, EXCLUDED.dsid, EXCLUDED.dsname, EXCLUDED.dsprefix, EXCLUDED.dateofcollection, EXCLUDED.dateoftransformation)";
|
|
|
|
inputStream.forEach(r -> this.jdbcTemplate.update(sql, r.getId(), r.getOriginalId(), r.getBody(), r.getProvenance().getDatasourceId(), r.getProvenance()
|
|
.getDatasourceName(), r.getProvenance().getNsPrefix(), r.getDateOfCollection(), r.getDateOfTransformation()));
|
|
|
|
}
|
|
|
|
private void createTableIfMissing(final String table) {
|
|
this.jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS " + table + " ("
|
|
+ "id text PRIMARY KEY, "
|
|
+ "originalid text NOT NULL, "
|
|
+ "body text NOT NULL, "
|
|
+ "dsid text, "
|
|
+ "dsname text, "
|
|
+ "dsprefix char(12), "
|
|
+ "dateofcollection timestamp NOT NULL, "
|
|
+ "dateoftransformation timestamp"
|
|
+ ")");
|
|
}
|
|
|
|
@Override
|
|
public Stream<MetadataRecord> streamEntries(final MDStoreVersion version) throws MDStoreManagerException {
|
|
return this.jdbcTemplate.queryForStream("select * from " + asTableName(version.getId()), mdstoreMapper());
|
|
}
|
|
|
|
@Override
|
|
public Set<String> fixInconsistencies(final boolean delete) throws MDStoreManagerException {
|
|
// TODO (LOW PRIORITY) Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public long countRecords(final String versionId) {
|
|
final Long res = this.jdbcTemplate.queryForObject("select count(*) from " + asTableName(versionId), Long.class);
|
|
return res != null ? res : 0;
|
|
}
|
|
|
|
private static String asTableName(final String id) {
|
|
// It should prevents from SQL Injection
|
|
if (id.matches("^[a-zA-Z0-9\\-]+$")) { return id.replace('-', '_').toLowerCase(); }
|
|
throw new IllegalArgumentException("Invalid mdId: " + id);
|
|
}
|
|
|
|
private RowMapper<MetadataRecord> mdstoreMapper() {
|
|
return (rs, rowNum) -> {
|
|
final MetadataRecord mr = new MetadataRecord();
|
|
mr.setId(rs.getString("id"));
|
|
mr.setOriginalId(rs.getString("originalid"));
|
|
mr.setBody(rs.getString("body"));
|
|
mr.setProvenance(new Provenance(rs.getString("dsid"), rs.getString("dsname"), rs.getString("dsprefix")));
|
|
mr.setEncoding(MetadataRecordEncoding.XML);
|
|
|
|
final Timestamp t1 = rs.getTimestamp("dateofcollection");
|
|
final Timestamp t2 = rs.getTimestamp("dateoftransformation");
|
|
if (t1 != null) {
|
|
mr.setDateOfCollection(t1.toLocalDateTime());
|
|
}
|
|
if (t2 != null) {
|
|
mr.setDateOfCollection(rs.getTimestamp("dateoftransformation").toLocalDateTime());
|
|
}
|
|
|
|
return mr;
|
|
};
|
|
}
|
|
|
|
}
|