aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/com/healthmarketscience/jackcess/Database.java
blob: d853fe8c6793713ebd699f7a5ece93d2d4159273 (plain)
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
/*
Copyright (c) 2013 James Ahlborn

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package com.healthmarketscience.jackcess;

import java.io.Closeable;
import java.io.File;
import java.io.Flushable;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import com.healthmarketscience.jackcess.expr.EvalConfig;
import com.healthmarketscience.jackcess.query.Query;
import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import com.healthmarketscience.jackcess.util.ColumnValidatorFactory;
import com.healthmarketscience.jackcess.util.ErrorHandler;
import com.healthmarketscience.jackcess.util.LinkResolver;
import com.healthmarketscience.jackcess.util.TableIterableBuilder;

/**
 * An Access database instance.  A new instance can be instantiated by opening
 * an existing database file ({@link DatabaseBuilder#open(File)}) or creating
 * a new database file ({@link DatabaseBuilder#create(Database.FileFormat,File)}) (for
 * more advanced opening/creating use {@link DatabaseBuilder}).  Once a
 * Database has been opened, you can interact with the data via the relevant
 * {@link Table}.  When a Database instance is no longer useful, it should
 * <b>always</b> be closed ({@link #close}) to avoid corruption.
 * <p/>
 * Database instances (and all the related objects) are <i>not</i>
 * thread-safe.  However, separate Database instances (and their respective
 * objects) can be used by separate threads without a problem.
 * <p/>
 * Database instances do not implement any "transactional" support, and
 * therefore concurrent editing of the same database file by multiple Database
 * instances (or with outside programs such as MS Access) <i>will generally
 * result in database file corruption</i>.
 *
 * @author James Ahlborn
 * @usage _general_class_
 */
public interface Database extends Iterable<Table>, Closeable, Flushable
{
  /** default value for the auto-sync value ({@code true}).  this is slower,
   *  but leaves more chance of a useable database in the face of failures.
   * @usage _general_field_
   */
  public static final boolean DEFAULT_AUTO_SYNC = true;

  /**
   * the default sort order for table columns.
   * @usage _intermediate_field_
   */
  public static final Table.ColumnOrder DEFAULT_COLUMN_ORDER =
    Table.ColumnOrder.DATA;

  /** system property which can be used to set the default TimeZone used for
   *  date calculations.
   * @usage _general_field_
   */
  public static final String TIMEZONE_PROPERTY =
    "com.healthmarketscience.jackcess.timeZone";

  /** system property prefix which can be used to set the default Charset
   *  used for text data (full property includes the JetFormat version).
   * @usage _general_field_
   */
  public static final String CHARSET_PROPERTY_PREFIX =
    "com.healthmarketscience.jackcess.charset.";

  /** system property which can be used to set the path from which classpath
   *  resources are loaded (must end with a "/" if non-empty).  Default value
   *  is {@value com.healthmarketscience.jackcess.impl.DatabaseImpl#DEFAULT_RESOURCE_PATH}
   *  if unspecified.
   * @usage _general_field_
   */
  public static final String RESOURCE_PATH_PROPERTY =
    "com.healthmarketscience.jackcess.resourcePath";

  /** (boolean) system property which can be used to indicate that the current
   *  vm has a poor nio implementation (specifically for
   *  {@code FileChannel.transferFrom})
   * @usage _intermediate_field_
   */
  public static final String BROKEN_NIO_PROPERTY =
    "com.healthmarketscience.jackcess.brokenNio";

  /** system property which can be used to set the default sort order for
   *  table columns.  Value should be one {@link Table.ColumnOrder} enum
   *  values.
   * @usage _intermediate_field_
   */
  public static final String COLUMN_ORDER_PROPERTY =
    "com.healthmarketscience.jackcess.columnOrder";

  /** system property which can be used to set the default enforcement of
   * foreign-key relationships.  Defaults to {@code true}.
   * @usage _general_field_
   */
  public static final String FK_ENFORCE_PROPERTY =
    "com.healthmarketscience.jackcess.enforceForeignKeys";

  /** system property which can be used to set the default allow auto number
   * insert policy.  Defaults to {@code false}.
   * @usage _general_field_
   */
  public static final String ALLOW_AUTONUM_INSERT_PROPERTY =
    "com.healthmarketscience.jackcess.allowAutoNumberInsert";

  /** system property which can be used to enable expression evaluation
   * (currently experimental).  Defaults to {@code false}.
   * @usage _general_field_
   */
  public static final String ENABLE_EXPRESSION_EVALUATION_PROPERTY =
    "com.healthmarketscience.jackcess.enableExpressionEvaluation";

  /**
   * Enum which indicates which version of Access created the database.
   * @usage _general_class_
   */
  public enum FileFormat {

    /** A database which was created by MS Access 97 */
    V1997(".mdb"),
    /** A database which was most likely created programmatically (e.g. using
        windows ADOX) */
    GENERIC_JET4(".mdb"),
    /** A database which was created by MS Access 2000 */
    V2000(".mdb"),
    /** A database which was created by MS Access 2002/2003 */
    V2003(".mdb"),
    /** A database which was created by MS Access 2007 */
    V2007(".accdb"),
    /** A database which was created by MS Access 2010+ */
    V2010(".accdb"),
    /** A database which was created by MS Access 2016+ */
    V2016(".accdb"),
    /** A database which was created by MS Money */
    MSISAM(".mny");

    private final String _ext;

    private FileFormat(String ext) {
      _ext = ext;
    }

    /**
     * @return the file extension used for database files with this format.
     */
    public String getFileExtension() { return _ext; }

    @Override
    public String toString() {
      return name() + " [" + DatabaseImpl.getFileFormatDetails(this).getFormat() + "]";
    }
  }

  /**
   * Returns the File underlying this Database
   */
  public File getFile();

  /**
   * @return The names of all of the user tables
   * @usage _general_method_
   */
  public Set<String> getTableNames() throws IOException;

  /**
   * @return The names of all of the system tables (String).  Note, in order
   *         to read these tables, you must use {@link #getSystemTable}.
   *         <i>Extreme care should be taken if modifying these tables
   *         directly!</i>.
   * @usage _intermediate_method_
   */
  public Set<String> getSystemTableNames() throws IOException;

  /**
   * @return an unmodifiable Iterator of the user Tables in this Database.
   * @throws RuntimeIOException if an IOException is thrown by one of the
   *         operations, the actual exception will be contained within
   * @throws ConcurrentModificationException if a table is added to the
   *         database while an Iterator is in use.
   * @usage _general_method_
   */
  public Iterator<Table> iterator();

  /**
   * Convenience method for constructing a new TableIterableBuilder for this
   * cursor.  A TableIterableBuilder provides a variety of options for more
   * flexible iteration of Tables.
   */
  public TableIterableBuilder newIterable();

  /**
   * @param name User table name (case-insensitive)
   * @return The Table, or null if it doesn't exist (or is a system table)
   * @usage _general_method_
   */
  public Table getTable(String name) throws IOException;

  /**
   * @param name Table name (case-insensitive), may be any table type
   *             (i.e. includes system or linked tables).
   * @return The meta data for the table, or null if it doesn't exist
   * @usage _intermediate_method_
   */
  public TableMetaData getTableMetaData(String name) throws IOException;

  /**
   * Finds all the relationships in the database between the given tables.
   * @usage _intermediate_method_
   */
  public List<Relationship> getRelationships(Table table1, Table table2)
    throws IOException;

  /**
   * Finds all the relationships in the database for the given table.
   * @usage _intermediate_method_
   */
  public List<Relationship> getRelationships(Table table) throws IOException;

  /**
   * Finds all the relationships in the database in <i>non-system</i> tables.
   * </p>
   * Warning, this may load <i>all</i> the Tables (metadata, not data) in the
   * database which could cause memory issues.
   * @usage _intermediate_method_
   */
  public List<Relationship> getRelationships() throws IOException;

  /**
   * Finds <i>all</i> the relationships in the database, <i>including system
   * tables</i>.
   * </p>
   * Warning, this may load <i>all</i> the Tables (metadata, not data) in the
   * database which could cause memory issues.
   * @usage _intermediate_method_
   */
  public List<Relationship> getSystemRelationships()
    throws IOException;

  /**
   * Finds all the queries in the database.
   * @usage _intermediate_method_
   */
  public List<Query> getQueries() throws IOException;

  /**
   * Returns a reference to <i>any</i> available table in this access
   * database, including system tables.
   * <p>
   * Warning, this method is not designed for common use, only for the
   * occassional time when access to a system table is necessary.  Messing
   * with system tables can strip the paint off your house and give your whole
   * family a permanent, orange afro.  You have been warned.
   *
   * @param tableName Table name, may be a system table
   * @return The table, or {@code null} if it doesn't exist
   * @usage _intermediate_method_
   */
  public Table getSystemTable(String tableName) throws IOException;

  /**
   * @return the core properties for the database
   * @usage _general_method_
   */
  public PropertyMap getDatabaseProperties() throws IOException;

  /**
   * @return the summary properties for the database
   * @usage _general_method_
   */
  public PropertyMap getSummaryProperties() throws IOException;

  /**
   * @return the user-defined properties for the database
   * @usage _general_method_
   */
  public PropertyMap getUserDefinedProperties() throws IOException;

  /**
   * @return the current database password, or {@code null} if none set.
   * @usage _general_method_
   */
  public String getDatabasePassword() throws IOException;

  /**
   * Create a new table in this database
   * @param name Name of the table to create in this database
   * @param linkedDbName path to the linked database
   * @param linkedTableName name of the table in the linked database
   * @usage _general_method_
   */
  public void createLinkedTable(String name, String linkedDbName,
                                String linkedTableName)
    throws IOException;

  /**
   * Flushes any current changes to the database file (and any linked
   * databases) to disk.
   * @usage _general_method_
   */
  public void flush() throws IOException;

  /**
   * Close the database file (and any linked databases).  A Database
   * <b>must</b> be closed after use or changes could be lost and the Database
   * file corrupted.  A Database instance should be treated like any other
   * external resource which would be closed in a finally block (e.g. an
   * OutputStream or jdbc Connection).
   * @usage _general_method_
   */
  public void close() throws IOException;

  /**
   * Gets the currently configured ErrorHandler (always non-{@code null}).
   * This will be used to handle all errors unless overridden at the Table or
   * Cursor level.
   * @usage _intermediate_method_
   */
  public ErrorHandler getErrorHandler();

  /**
   * Sets a new ErrorHandler.  If {@code null}, resets to the
   * {@link ErrorHandler#DEFAULT}.
   * @usage _intermediate_method_
   */
  public void setErrorHandler(ErrorHandler newErrorHandler);

  /**
   * Gets the currently configured LinkResolver (always non-{@code null}).
   * This will be used to handle all linked database loading.
   * @usage _intermediate_method_
   */
  public LinkResolver getLinkResolver();

  /**
   * Sets a new LinkResolver.  If {@code null}, resets to the
   * {@link LinkResolver#DEFAULT}.
   * @usage _intermediate_method_
   */
  public void setLinkResolver(LinkResolver newLinkResolver);

  /**
   * Returns an unmodifiable view of the currently loaded linked databases,
   * mapped from the linked database file name to the linked database.  This
   * information may be useful for implementing a LinkResolver.
   * @usage _intermediate_method_
   */
  public Map<String,Database> getLinkedDatabases();


  /**
   * Returns {@code true} if this Database links to the given Table, {@code
   * false} otherwise.
   * @usage _general_method_
   */
  public boolean isLinkedTable(Table table) throws IOException;

  /**
   * Gets currently configured TimeZone (always non-{@code null}).
   * @usage _intermediate_method_
   */
  public TimeZone getTimeZone();

  /**
   * Sets a new TimeZone.  If {@code null}, resets to the default value.
   * @usage _intermediate_method_
   */
  public void setTimeZone(TimeZone newTimeZone);

  /**
   * Gets currently configured Charset (always non-{@code null}).
   * @usage _intermediate_method_
   */
  public Charset getCharset();

  /**
   * Sets a new Charset.  If {@code null}, resets to the default value.
   * @usage _intermediate_method_
   */
  public void setCharset(Charset newCharset);

  /**
   * Gets currently configured {@link Table.ColumnOrder} (always non-{@code
   * null}).
   * @usage _intermediate_method_
   */
  public Table.ColumnOrder getColumnOrder();

  /**
   * Sets a new Table.ColumnOrder.  If {@code null}, resets to the default value.
   * @usage _intermediate_method_
   */
  public void setColumnOrder(Table.ColumnOrder newColumnOrder);

  /**
   * Gets current foreign-key enforcement policy.
   * @usage _intermediate_method_
   */
  public boolean isEnforceForeignKeys();

  /**
   * Sets a new foreign-key enforcement policy.  If {@code null}, resets to
   * the default value.
   * @usage _intermediate_method_
   */
  public void setEnforceForeignKeys(Boolean newEnforceForeignKeys);

  /**
   * Gets current allow auto number insert policy.  By default, jackcess does
   * not allow auto numbers to be inserted or updated directly (they are
   * always handled internally by the Table).  Setting this policy to {@code
   * true} allows the caller to optionally set the value explicitly when
   * adding or updating rows (if a value is not provided, it will still be
   * handled internally by the Table).  This value can be set database-wide
   * using {@link #setAllowAutoNumberInsert} and/or on a per-table basis using
   * {@link Table#setAllowAutoNumberInsert} (and/or on a jvm-wide using the
   * {@link #ALLOW_AUTONUM_INSERT_PROPERTY} system property).  Note that
   * <i>enabling this feature should be done with care</i> to reduce the
   * chances of screwing up the database.
   *
   * @usage _intermediate_method_
   */
  public boolean isAllowAutoNumberInsert();

  /**
   * Sets the new auto number insert policy for the database (unless
   * overridden at the Table level).  If {@code null}, resets to the default
   * value.
   * @usage _intermediate_method_
   */
  public void setAllowAutoNumberInsert(Boolean allowAutoNumInsert);

  /**
   * Gets the current expression evaluation policy.  Expression evaluation is
   * currently an experimental feature, and is therefore disabled by default.
   */
  public boolean isEvaluateExpressions();

  /**
   * Sets the current expression evaluation policy.  Expression evaluation is
   * currently an experimental feature, and is therefore disabled by default.
   * If {@code null}, resets to the default value.
   * @usage _intermediate_method_
   */
  public void setEvaluateExpressions(Boolean evaluateExpressions);

  /**
   * Gets currently configured ColumnValidatorFactory (always non-{@code null}).
   * @usage _intermediate_method_
   */
  public ColumnValidatorFactory getColumnValidatorFactory();

  /**
   * Sets a new ColumnValidatorFactory.  If {@code null}, resets to the
   * default value.  The configured ColumnValidatorFactory will be used to
   * create ColumnValidator instances on any <i>user</i> tables loaded from
   * this point onward (this will not be used for system tables).
   * @usage _intermediate_method_
   */
  public void setColumnValidatorFactory(ColumnValidatorFactory newFactory);

  /**
   * Returns the FileFormat of this database (which may involve inspecting the
   * database itself).
   * @throws IllegalStateException if the file format cannot be determined
   * @usage _general_method_
   */
  public FileFormat getFileFormat() throws IOException;

  /**
   * Returns the EvalConfig for configuring expression evaluation.
   */
  public EvalConfig getEvalConfig();
}