|
|
@ -1,7 +1,6 @@ |
|
|
|
/* © SRSoftware 2024 */ |
|
|
|
/* © SRSoftware 2024 */ |
|
|
|
package de.srsoftware.cal.db; |
|
|
|
package de.srsoftware.cal.db; |
|
|
|
|
|
|
|
|
|
|
|
import static de.srsoftware.cal.db.Database.slug; |
|
|
|
|
|
|
|
import static de.srsoftware.cal.db.Fields.*; |
|
|
|
import static de.srsoftware.cal.db.Fields.*; |
|
|
|
import static de.srsoftware.cal.db.Fields.ALL; |
|
|
|
import static de.srsoftware.cal.db.Fields.ALL; |
|
|
|
import static de.srsoftware.tools.Optionals.*; |
|
|
|
import static de.srsoftware.tools.Optionals.*; |
|
|
@ -27,14 +26,12 @@ import java.util.*; |
|
|
|
|
|
|
|
|
|
|
|
public class MariaDB implements Database { |
|
|
|
public class MariaDB implements Database { |
|
|
|
private static final System.Logger LOG = System.getLogger(MariaDB.class.getSimpleName()); |
|
|
|
private static final System.Logger LOG = System.getLogger(MariaDB.class.getSimpleName()); |
|
|
|
private static final String ADD_SLUG = "ALTER TABLE appointments ADD slug VARCHAR(255) UNIQUE"; |
|
|
|
|
|
|
|
private static final String APPOINTMENTS = "appointments"; |
|
|
|
private static final String APPOINTMENTS = "appointments"; |
|
|
|
private static final String APPOINTMENT_TAGS = "appointment_tags"; |
|
|
|
private static final String APPOINTMENT_TAGS = "appointment_tags"; |
|
|
|
private static final String APPOINTMENT_URLS = "appointment_urls"; |
|
|
|
private static final String APPOINTMENT_URLS = "appointment_urls"; |
|
|
|
private static final String URLS = "urls"; |
|
|
|
private static final String URLS = "urls"; |
|
|
|
private static final String APPOINTMENT_ATTACHMENTS = "appointment_attachments"; |
|
|
|
private static final String APPOINTMENT_ATTACHMENTS = "appointment_attachments"; |
|
|
|
private static final String TAGS = "tags"; |
|
|
|
private static final String TAGS = "tags"; |
|
|
|
private static final String SLUG = "slug"; |
|
|
|
|
|
|
|
private static Connection connection; |
|
|
|
private static Connection connection; |
|
|
|
|
|
|
|
|
|
|
|
private MariaDB(Connection conn) throws SQLException { |
|
|
|
private MariaDB(Connection conn) throws SQLException { |
|
|
@ -53,47 +50,9 @@ public class MariaDB implements Database { |
|
|
|
switch (version) { |
|
|
|
switch (version) { |
|
|
|
case 0: |
|
|
|
case 0: |
|
|
|
createTables(); |
|
|
|
createTables(); |
|
|
|
case 1: |
|
|
|
|
|
|
|
update1(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void update1() throws SQLException { |
|
|
|
|
|
|
|
LOG.log(INFO, "Updating db scheme from version 1 to 2…"); |
|
|
|
|
|
|
|
var list = new ArrayList<Appointment>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
connection.setAutoCommit(false); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOG.log(DEBUG, "Adding slug column…"); |
|
|
|
|
|
|
|
connection.prepareStatement(ADD_SLUG).execute(); |
|
|
|
|
|
|
|
var slugMap = new HashMap<Long, String>(); |
|
|
|
|
|
|
|
LOG.log(DEBUG, "Reading existing appointments…"); |
|
|
|
|
|
|
|
var rs = select(ALL).from("appointments").exec(connection); |
|
|
|
|
|
|
|
while (rs.next()) { |
|
|
|
|
|
|
|
var id = rs.getLong(AID); |
|
|
|
|
|
|
|
var location = nullable(nullIfEmpty(rs.getString("location"))); |
|
|
|
|
|
|
|
if (location.isEmpty()) continue; |
|
|
|
|
|
|
|
var title = rs.getString("title"); |
|
|
|
|
|
|
|
LOG.log(TRACE, () -> "%s: %s".formatted(id, title)); |
|
|
|
|
|
|
|
var descr = rs.getString("description"); |
|
|
|
|
|
|
|
if (allEmpty(title, descr)) continue; |
|
|
|
|
|
|
|
var start = nullable(rs.getTimestamp("start")).map(Timestamp::toLocalDateTime); |
|
|
|
|
|
|
|
if (start.isEmpty()) continue; |
|
|
|
|
|
|
|
var slug = slug(location.get(), start.get()); |
|
|
|
|
|
|
|
slugMap.put(id, slug); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
rs.close(); |
|
|
|
|
|
|
|
LOG.log(DEBUG, "Creating slugs…"); |
|
|
|
|
|
|
|
var query = updateIgnore("appointments").set("slug").where(AID, equal(MARK)).prepare(connection); |
|
|
|
|
|
|
|
for (var entry : slugMap.entrySet()) { |
|
|
|
|
|
|
|
query.apply(entry.getValue(), entry.getKey()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOG.log(DEBUG, "Writing new db version marker…"); |
|
|
|
|
|
|
|
update("config").set("value").where("keyname", equal("dbversion")).prepare(connection).apply(2); |
|
|
|
|
|
|
|
connection.setAutoCommit(true); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void createTables() { |
|
|
|
private void createTables() { |
|
|
|
throw new RuntimeException("%s.createTables() not implemented!"); |
|
|
|
throw new RuntimeException("%s.createTables() not implemented!"); |
|
|
|
} |
|
|
|
} |
|
|
@ -102,8 +61,8 @@ public class MariaDB implements Database { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Result<Appointment> add(Appointment appointment) { |
|
|
|
public Result<Appointment> add(Appointment appointment) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
ResultSet keys = insertInto(APPOINTMENTS, TITLE, DESCRIPTION, START, END, LOCATION, COORDS, SLUG) //
|
|
|
|
ResultSet keys = insertInto(APPOINTMENTS, TITLE, DESCRIPTION, START, END, LOCATION, COORDS) //
|
|
|
|
.values(appointment.title(), appointment.description(), appointment.start(), appointment.end().orElse(null), appointment.location(), appointment.coords().orElse(null), appointment.slug()) |
|
|
|
.values(appointment.title(), appointment.description(), appointment.start(), appointment.end().orElse(null), appointment.location(), appointment.coords().orElse(null)) |
|
|
|
.execute(connection) |
|
|
|
.execute(connection) |
|
|
|
.getGeneratedKeys(); |
|
|
|
.getGeneratedKeys(); |
|
|
|
Appointment saved = null; |
|
|
|
Appointment saved = null; |
|
|
@ -215,14 +174,14 @@ public class MariaDB implements Database { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Result<Appointment> loadEvent(String slug) { |
|
|
|
public Result<Appointment> loadEvent(String location, LocalDateTime start) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
var rs = select(ALL).from(APPOINTMENTS).where(SLUG, equal(slug)).exec(connection); |
|
|
|
var rs = select(ALL).from(APPOINTMENTS).where(LOCATION, equal(location)).where(START, equal(Timestamp.valueOf(start))).exec(connection); |
|
|
|
Result<Appointment> result = rs.next() ? createAppointmentOf(rs).map(MariaDB::loadExtra) : Error.format("Failed to find appointment with slug %s", slug); |
|
|
|
Result<Appointment> result = rs.next() ? createAppointmentOf(rs).map(MariaDB::loadExtra) : Error.format("Failed to find appointment starting %s @ %s".formatted(start, location)); |
|
|
|
rs.close(); |
|
|
|
rs.close(); |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} catch (SQLException e) { |
|
|
|
} catch (SQLException e) { |
|
|
|
return Error.of("Failed to load appointment with slug = %s".formatted(slug), e); |
|
|
|
return Error.of("Failed to load appointment starting %s @ %s".formatted(start, location), e); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -295,12 +254,10 @@ public class MariaDB implements Database { |
|
|
|
var title = results.getString("title"); |
|
|
|
var title = results.getString("title"); |
|
|
|
var description = results.getString("description"); |
|
|
|
var description = results.getString("description"); |
|
|
|
if (allEmpty(title, description)) return Error.format("Title and Description of appointment %s are empty", id); |
|
|
|
if (allEmpty(title, description)) return Error.format("Title and Description of appointment %s are empty", id); |
|
|
|
var start = results.getTimestamp("start").toLocalDateTime(); |
|
|
|
var start = results.getTimestamp("start").toLocalDateTime(); |
|
|
|
var end = nullable(results.getTimestamp("end")).map(Timestamp::toLocalDateTime).orElse(null); |
|
|
|
var end = nullable(results.getTimestamp("end")).map(Timestamp::toLocalDateTime).orElse(null); |
|
|
|
var location = results.getString("location"); |
|
|
|
var location = results.getString("location"); |
|
|
|
var slug = results.getString("slug"); |
|
|
|
var appointment = new BaseAppointment(id, title, description, start, end, location); |
|
|
|
if (slug == null) slug = slug(location, start); |
|
|
|
|
|
|
|
var appointment = new BaseAppointment(id, title, description, start, end, location, slug); |
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
var tags = nullIfEmpty(results.getString("tags")); |
|
|
|
var tags = nullIfEmpty(results.getString("tags")); |
|
|
|
if (tags != null) appointment.tags(tags.split(",")); |
|
|
|
if (tags != null) appointment.tags(tags.split(",")); |
|
|
|