Skip to content

Commit 72b26e0

Browse files
committed
Prepare for linked files index (full-text)
1 parent c6869cc commit 72b26e0

File tree

7 files changed

+138
-98
lines changed

7 files changed

+138
-98
lines changed

src/main/java/org/jabref/logic/search/IndexManager.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import org.jabref.logic.preferences.CliPreferences;
1111
import org.jabref.logic.search.indexing.DefaultLinkedFilesIndexer;
12-
import org.jabref.logic.search.indexing.PostgreIndexer;
12+
import org.jabref.logic.search.indexing.BibFieldsIndexer;
1313
import org.jabref.logic.search.indexing.ReadOnlyLinkedFilesIndexer;
1414
import org.jabref.logic.search.retrieval.BibFieldsSearcher;
1515
import org.jabref.logic.search.retrieval.LinkedFilesSearcher;
@@ -39,7 +39,7 @@ public class IndexManager {
3939
private final BooleanProperty shouldIndexLinkedFiles;
4040
private final BooleanProperty isLinkedFilesIndexerBlocked = new SimpleBooleanProperty(false);
4141
private final ChangeListener<Boolean> preferencesListener;
42-
private final PostgreIndexer bibFieldsIndexer;
42+
private final BibFieldsIndexer bibFieldsIndexer;
4343
private final LuceneIndexer linkedFilesIndexer;
4444
private final BibFieldsSearcher bibFieldsSearcher;
4545
private final LinkedFilesSearcher linkedFilesSearcher;
@@ -52,7 +52,7 @@ public IndexManager(BibDatabaseContext databaseContext, TaskExecutor executor, C
5252
this.shouldIndexLinkedFiles.addListener(preferencesListener);
5353

5454
PostgreServer postgreServer = Injector.instantiateModelOrService(PostgreServer.class);
55-
bibFieldsIndexer = new PostgreIndexer(preferences.getBibEntryPreferences(), databaseContext, postgreServer.getConnection());
55+
bibFieldsIndexer = new BibFieldsIndexer(preferences.getBibEntryPreferences(), databaseContext, postgreServer.getConnection());
5656

5757
LuceneIndexer indexer;
5858
try {
@@ -229,7 +229,7 @@ public SearchResults search(SearchQuery query) {
229229
if (query.getSearchFlags().contains(SearchFlags.FULLTEXT)) {
230230
// TODO: merge results from lucene and postgres
231231
} else {
232-
query.setSearchResults(bibFieldsSearcher.search(query.getSqlQuery(bibFieldsIndexer.getTableName())));
232+
query.setSearchResults(bibFieldsSearcher.search(query.getSqlQuery(bibFieldsIndexer.getMainTable())));
233233
}
234234
return query.getSearchResults();
235235
}

src/main/java/org/jabref/logic/search/PostgreServer.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66

77
import javax.sql.DataSource;
88

9+
import org.jabref.logic.util.Directories;
10+
911
import io.zonky.test.db.postgres.embedded.EmbeddedPostgres;
1012
import org.slf4j.Logger;
1113
import org.slf4j.LoggerFactory;
1214

15+
import static org.jabref.model.search.PostgreConstants.BIB_FIELDS_SCHEME;
16+
import static org.jabref.model.search.PostgreConstants.LINKED_FILES_SCHEME;
17+
1318
public class PostgreServer {
1419
private static final Logger LOGGER = LoggerFactory.getLogger(PostgreServer.class);
1520
private final EmbeddedPostgres embeddedPostgres;
@@ -19,6 +24,9 @@ public PostgreServer() {
1924
EmbeddedPostgres embeddedPostgres;
2025
try {
2126
embeddedPostgres = EmbeddedPostgres.builder()
27+
.setCleanDataDirectory(false)
28+
.setDataDirectory(Directories.getPostgresDataDirectory())
29+
.setPort(10456)
2230
.start();
2331
LOGGER.info("Postgres server started, connection port: {}", embeddedPostgres.getPort());
2432
} catch (IOException e) {
@@ -29,9 +37,22 @@ public PostgreServer() {
2937
}
3038

3139
this.embeddedPostgres = embeddedPostgres;
32-
// TODO: Use the default database (postgres) and the default schema (public) or create a new one?
3340
this.dataSource = embeddedPostgres.getPostgresDatabase();
3441
addTrigramExtension();
42+
createScheme();
43+
}
44+
45+
private void createScheme() {
46+
try (Connection connection = getConnection()) {
47+
if (connection != null) {
48+
LOGGER.debug("Creating scheme for bib fields and linked files");
49+
connection.createStatement().execute("DROP SCHEMA IF EXISTS " + BIB_FIELDS_SCHEME);
50+
connection.createStatement().execute("CREATE SCHEMA " + BIB_FIELDS_SCHEME);
51+
connection.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + LINKED_FILES_SCHEME);
52+
}
53+
} catch (SQLException e) {
54+
LOGGER.error("Could not create scheme for bib fields and linked files", e);
55+
}
3556
}
3657

3758
private void addTrigramExtension() {

src/main/java/org/jabref/logic/search/indexing/PostgreIndexer.java renamed to src/main/java/org/jabref/logic/search/indexing/BibFieldsIndexer.java

Lines changed: 92 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,47 @@
2727
import org.slf4j.Logger;
2828
import org.slf4j.LoggerFactory;
2929

30-
public class PostgreIndexer {
31-
private static final Logger LOGGER = LoggerFactory.getLogger(PostgreIndexer.class);
30+
import static org.jabref.model.search.PostgreConstants.ENTRY_ID;
31+
import static org.jabref.model.search.PostgreConstants.FIELD_NAME;
32+
import static org.jabref.model.search.PostgreConstants.FIELD_VALUE_LITERAL;
33+
import static org.jabref.model.search.PostgreConstants.FIELD_VALUE_TRANSFORMED;
34+
import static org.jabref.model.search.PostgreConstants.TABLE_NAME_SUFFIX;
35+
36+
public class BibFieldsIndexer {
37+
private static final Logger LOGGER = LoggerFactory.getLogger(BibFieldsIndexer.class);
3238
private static final LatexToUnicodeFormatter LATEX_TO_UNICODE_FORMATTER = new LatexToUnicodeFormatter();
3339
private static final Pattern GROUPS_SEPARATOR_REGEX = Pattern.compile("\s*,\s*");
34-
private static int NUMBER_OF_UNSAVED_LIBRARIES = 1;
3540

3641
private final BibDatabaseContext databaseContext;
3742
private final Connection connection;
3843
private final String libraryName;
39-
private final String tableName;
40-
private final String tableNameSplitValues;
44+
private final String mainTable;
45+
private final String schemaMainTableReference;
46+
private final String splitValuesTable;
47+
private final String schemaSplitValuesTableReference;
4148
private final Character keywordSeparator;
4249

43-
public PostgreIndexer(BibEntryPreferences bibEntryPreferences, BibDatabaseContext databaseContext, Connection connection) {
50+
public BibFieldsIndexer(BibEntryPreferences bibEntryPreferences, BibDatabaseContext databaseContext, Connection connection) {
4451
this.databaseContext = databaseContext;
4552
this.connection = connection;
4653
this.keywordSeparator = bibEntryPreferences.getKeywordSeparator();
4754
this.libraryName = databaseContext.getDatabasePath().map(path -> path.getFileName().toString()).orElse("unsaved");
48-
if ("unsaved".equals(databaseContext.getPostgreTableName())) {
49-
this.tableName = "unsaved" + NUMBER_OF_UNSAVED_LIBRARIES++;
50-
} else {
51-
this.tableName = databaseContext.getPostgreTableName();
52-
}
53-
tableNameSplitValues = tableName + PostgreConstants.TABLE_NAME_SUFFIX;
55+
56+
this.mainTable = databaseContext.getUniqueName();
57+
this.splitValuesTable = mainTable + TABLE_NAME_SUFFIX;
58+
59+
this.schemaMainTableReference = """
60+
"%s"."%s"
61+
""".formatted(PostgreConstants.BIB_FIELDS_SCHEME, mainTable);
62+
this.schemaSplitValuesTableReference = """
63+
"%s"."%s"
64+
""".formatted(PostgreConstants.BIB_FIELDS_SCHEME, splitValuesTable);
65+
// TODO: Set-up should be in a background task
5466
setup();
5567
}
5668

57-
public String getTableName() {
58-
return tableName;
69+
public String getMainTable() {
70+
return mainTable;
5971
}
6072

6173
/**
@@ -64,35 +76,34 @@ public String getTableName() {
6476
private void setup() {
6577
try {
6678
connection.createStatement().executeUpdate("""
67-
CREATE TABLE IF NOT EXISTS "%s" (
79+
CREATE TABLE IF NOT EXISTS %s (
6880
%s TEXT NOT NULL,
6981
%s TEXT NOT NULL,
7082
%s TEXT,
7183
%s TEXT,
7284
PRIMARY KEY (%s, %s)
7385
)
7486
""".formatted(
75-
tableName,
76-
PostgreConstants.ENTRY_ID,
77-
PostgreConstants.FIELD_NAME,
78-
PostgreConstants.FIELD_VALUE_LITERAL,
79-
PostgreConstants.FIELD_VALUE_TRANSFORMED,
80-
PostgreConstants.ENTRY_ID,
81-
PostgreConstants.FIELD_NAME));
87+
schemaMainTableReference,
88+
ENTRY_ID,
89+
FIELD_NAME,
90+
FIELD_VALUE_LITERAL,
91+
FIELD_VALUE_TRANSFORMED,
92+
ENTRY_ID, FIELD_NAME));
8293

8394
connection.createStatement().executeUpdate("""
84-
CREATE TABLE IF NOT EXISTS "%s" (
95+
CREATE TABLE IF NOT EXISTS %s (
8596
%s TEXT NOT NULL,
8697
%s TEXT NOT NULL,
8798
%s TEXT,
8899
%s TEXT
89100
)
90101
""".formatted(
91-
tableNameSplitValues,
92-
PostgreConstants.ENTRY_ID,
93-
PostgreConstants.FIELD_NAME,
94-
PostgreConstants.FIELD_VALUE_LITERAL,
95-
PostgreConstants.FIELD_VALUE_TRANSFORMED));
102+
schemaSplitValuesTableReference,
103+
ENTRY_ID,
104+
FIELD_NAME,
105+
FIELD_VALUE_LITERAL,
106+
FIELD_VALUE_TRANSFORMED));
96107

97108
LOGGER.debug("Created tables for library: {}", libraryName);
98109
} catch (SQLException e) {
@@ -101,66 +112,66 @@ PRIMARY KEY (%s, %s)
101112
try {
102113
// region btree index on id column
103114
connection.createStatement().executeUpdate("""
104-
CREATE INDEX "%s" ON "%s" ("%s")
115+
CREATE INDEX "%s_%s_index" ON %s ("%s")
105116
""".formatted(
106-
PostgreConstants.ENTRY_ID.getIndexName(tableName),
107-
tableName,
108-
PostgreConstants.ENTRY_ID));
117+
mainTable, ENTRY_ID,
118+
schemaMainTableReference,
119+
ENTRY_ID));
109120

110121
connection.createStatement().executeUpdate("""
111-
CREATE INDEX "%s" ON "%s" ("%s")
122+
CREATE INDEX "%s_%s_index" ON %s ("%s")
112123
""".formatted(
113-
PostgreConstants.ENTRY_ID.getIndexName(tableNameSplitValues),
114-
tableName,
115-
PostgreConstants.ENTRY_ID));
124+
splitValuesTable, ENTRY_ID,
125+
schemaSplitValuesTableReference,
126+
ENTRY_ID));
116127
// endregion
117128

118129
// region btree index on field name column
119130
connection.createStatement().executeUpdate("""
120-
CREATE INDEX "%s" ON "%s" ("%s")
131+
CREATE INDEX "%s_%s_index" ON %s ("%s")
121132
""".formatted(
122-
PostgreConstants.FIELD_NAME.getIndexName(tableName),
123-
tableName,
124-
PostgreConstants.FIELD_NAME));
133+
mainTable, FIELD_NAME,
134+
schemaMainTableReference,
135+
FIELD_NAME));
125136

126137
connection.createStatement().executeUpdate("""
127-
CREATE INDEX "%s" ON "%s" ("%s")
138+
CREATE INDEX "%s_%s_index" ON %s ("%s")
128139
""".formatted(
129-
PostgreConstants.FIELD_NAME.getIndexName(tableNameSplitValues),
130-
tableName,
131-
PostgreConstants.FIELD_NAME));
140+
splitValuesTable, FIELD_NAME,
141+
schemaSplitValuesTableReference,
142+
FIELD_NAME));
132143
// endregion
133144

134145
// trigram index on field value column
135146
connection.createStatement().executeUpdate("""
136-
CREATE INDEX "%s" ON "%s" USING gin ("%s" gin_trgm_ops)
147+
CREATE INDEX "%s_%s_index" ON %s USING gin ("%s" gin_trgm_ops)
137148
""".formatted(
138-
PostgreConstants.FIELD_VALUE_LITERAL.getIndexName(tableName),
139-
tableName,
140-
PostgreConstants.FIELD_VALUE_LITERAL));
149+
mainTable, FIELD_VALUE_LITERAL,
150+
schemaMainTableReference,
151+
FIELD_VALUE_LITERAL));
141152

142153
// trigram index on field value transformed column
143154
connection.createStatement().executeUpdate("""
144-
CREATE INDEX "%s" ON "%s" USING gin ("%s" gin_trgm_ops)
155+
CREATE INDEX "%s_%s_index" ON %s USING gin ("%s" gin_trgm_ops)
145156
""".formatted(
146-
PostgreConstants.FIELD_VALUE_TRANSFORMED.getIndexName(tableName),
147-
tableName,
148-
PostgreConstants.FIELD_VALUE_TRANSFORMED));
157+
mainTable, FIELD_VALUE_TRANSFORMED,
158+
schemaMainTableReference,
159+
FIELD_VALUE_TRANSFORMED));
149160

150161
// region btree index on spilt values column
151162
// connection.createStatement().executeUpdate("""
152163
// CREATE INDEX "%s" ON "%s" ("%s")
153164
// """.formatted(
154-
// PostgreConstants.FIELD_VALUE_LITERAL.getIndexName(tableNameSplitValues),
165+
// FIELD_VALUE_LITERAL.getIndexName(tableNameSplitValues),
155166
// tableName,
156-
// PostgreConstants.FIELD_VALUE_LITERAL));
167+
// FIELD_VALUE_LITERAL));
157168
//
158169
// connection.createStatement().executeUpdate("""
159170
// CREATE INDEX "%s" ON "%s" ("%s")
160171
// """.formatted(
161-
// PostgreConstants.FIELD_VALUE_TRANSFORMED.getIndexName(tableNameSplitValues),
172+
// FIELD_VALUE_TRANSFORMED.getIndexName(tableNameSplitValues),
162173
// tableName,
163-
// PostgreConstants.FIELD_VALUE_TRANSFORMED));
174+
// FIELD_VALUE_TRANSFORMED));
164175
// endregion
165176

166177
LOGGER.debug("Created indexes for library: {}", libraryName);
@@ -196,24 +207,24 @@ public void addToIndex(Collection<BibEntry> entries, BackgroundTask<?> task) {
196207

197208
private void addToIndex(BibEntry bibEntry) {
198209
String insertFieldQuery = """
199-
INSERT INTO "%s" ("%s", "%s", "%s", "%s")
210+
INSERT INTO %s ("%s", "%s", "%s", "%s")
200211
VALUES (?, ?, ?, ?)
201212
""".formatted(
202-
tableName,
203-
PostgreConstants.ENTRY_ID,
204-
PostgreConstants.FIELD_NAME,
205-
PostgreConstants.FIELD_VALUE_LITERAL,
206-
PostgreConstants.FIELD_VALUE_TRANSFORMED);
213+
schemaMainTableReference,
214+
ENTRY_ID,
215+
FIELD_NAME,
216+
FIELD_VALUE_LITERAL,
217+
FIELD_VALUE_TRANSFORMED);
207218

208219
String insertIntoSplitTable = """
209-
INSERT INTO "%s" ("%s", "%s", "%s", "%s")
220+
INSERT INTO %s ("%s", "%s", "%s", "%s")
210221
VALUES (?, ?, ?, ?)
211222
""".formatted(
212-
tableNameSplitValues,
213-
PostgreConstants.ENTRY_ID,
214-
PostgreConstants.FIELD_NAME,
215-
PostgreConstants.FIELD_VALUE_LITERAL,
216-
PostgreConstants.FIELD_VALUE_TRANSFORMED);
223+
schemaSplitValuesTableReference,
224+
ENTRY_ID,
225+
FIELD_NAME,
226+
FIELD_VALUE_LITERAL,
227+
FIELD_VALUE_TRANSFORMED);
217228

218229
try (PreparedStatement preparedStatement = connection.prepareStatement(insertFieldQuery);
219230
PreparedStatement preparedStatementSplitValues = connection.prepareStatement(insertIntoSplitTable)) {
@@ -339,9 +350,9 @@ public void removeFromIndex(Collection<BibEntry> entries, BackgroundTask<?> task
339350
private void removeFromIndex(BibEntry entry) {
340351
try {
341352
connection.createStatement().executeUpdate("""
342-
DELETE FROM "%s"
353+
DELETE FROM %s
343354
WHERE "%s" = '%s'
344-
""".formatted(tableName, PostgreConstants.ENTRY_ID, entry.getId()));
355+
""".formatted(schemaMainTableReference, ENTRY_ID, entry.getId()));
345356
LOGGER.debug("Entry {} removed from index", entry.getId());
346357
} catch (SQLException e) {
347358
LOGGER.error("Error deleting entry from index", e);
@@ -351,13 +362,13 @@ private void removeFromIndex(BibEntry entry) {
351362
public void updateEntry(BibEntry entry, Field field, String oldValue, String newValue) {
352363
try {
353364
String updateQuery = """
354-
INSERT INTO "%s" ("%s", "%s", "%s", "%s")
365+
INSERT INTO %s ("%s", "%s", "%s", "%s")
355366
VALUES (?, ?, ?, ?)
356-
""".formatted(tableName,
357-
PostgreConstants.ENTRY_ID,
358-
PostgreConstants.FIELD_NAME,
359-
PostgreConstants.FIELD_VALUE_LITERAL,
360-
PostgreConstants.FIELD_VALUE_TRANSFORMED);
367+
""".formatted(schemaSplitValuesTableReference,
368+
ENTRY_ID,
369+
FIELD_NAME,
370+
FIELD_VALUE_LITERAL,
371+
FIELD_VALUE_TRANSFORMED);
361372

362373
try (PreparedStatement preparedStatement = connection.prepareStatement(updateQuery)) {
363374
preparedStatement.setString(1, entry.getId());
@@ -383,8 +394,11 @@ private void closeIndex() {
383394
try {
384395
LOGGER.debug("Closing connection to Postgres server for library: {}", libraryName);
385396
connection.createStatement().executeUpdate("""
386-
DROP TABLE IF EXISTS "%s"
387-
""".formatted(tableName));
397+
DROP TABLE IF EXISTS %s
398+
""".formatted(schemaMainTableReference));
399+
connection.createStatement().executeUpdate("""
400+
DROP TABLE IF EXISTS %s
401+
""".formatted(schemaSplitValuesTableReference));
388402
connection.close();
389403
} catch (SQLException e) {
390404
LOGGER.error("Could not drop table for library: {}", libraryName, e);

src/main/java/org/jabref/logic/search/query/SearchToSqlVisitor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.List;
66
import java.util.Optional;
77

8+
import org.jabref.logic.search.indexing.BibFieldsIndexer;
89
import org.jabref.model.entry.field.InternalField;
910
import org.jabref.model.entry.field.StandardField;
1011
import org.jabref.search.SearchBaseVisitor;
@@ -20,7 +21,7 @@
2021
import static org.jabref.model.search.PostgreConstants.TABLE_NAME_SUFFIX;
2122

2223
/**
23-
* Converts to a query processable by the scheme created by {@link org.jabref.logic.search.indexing.PostgreIndexer}.
24+
* Converts to a query processable by the scheme created by {@link BibFieldsIndexer}.
2425
*
2526
* @implNote Similar class: {@link org.jabref.migrations.SearchToLuceneMigration}
2627
*/

0 commit comments

Comments
 (0)