You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /*
  2. Copyright (c) 2013 James Ahlborn
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package com.healthmarketscience.jackcess;
  14. import java.io.Closeable;
  15. import java.io.File;
  16. import java.io.Flushable;
  17. import java.io.IOException;
  18. import java.nio.charset.Charset;
  19. import java.nio.file.Path;
  20. import java.time.ZoneId;
  21. import java.util.ConcurrentModificationException;
  22. import java.util.Iterator;
  23. import java.util.List;
  24. import java.util.Map;
  25. import java.util.Set;
  26. import java.util.TimeZone;
  27. import java.util.stream.Stream;
  28. import java.util.stream.StreamSupport;
  29. import com.healthmarketscience.jackcess.expr.EvalConfig;
  30. import com.healthmarketscience.jackcess.impl.DatabaseImpl;
  31. import com.healthmarketscience.jackcess.query.Query;
  32. import com.healthmarketscience.jackcess.util.ColumnValidatorFactory;
  33. import com.healthmarketscience.jackcess.util.ErrorHandler;
  34. import com.healthmarketscience.jackcess.util.LinkResolver;
  35. import com.healthmarketscience.jackcess.util.TableIterableBuilder;
  36. /**
  37. * An Access database instance. A new instance can be instantiated by opening
  38. * an existing database file ({@link DatabaseBuilder#open(File)}) or creating
  39. * a new database file ({@link DatabaseBuilder#create(Database.FileFormat,File)}) (for
  40. * more advanced opening/creating use {@link DatabaseBuilder}). Once a
  41. * Database has been opened, you can interact with the data via the relevant
  42. * {@link Table}. When a Database instance is no longer useful, it should
  43. * <b>always</b> be closed ({@link #close}) to avoid corruption.
  44. * <p>
  45. * Database instances (and all the related objects) are <i>not</i>
  46. * thread-safe. However, separate Database instances (and their respective
  47. * objects) can be used by separate threads without a problem.
  48. * <p>
  49. * Database instances do not implement any "transactional" support, and
  50. * therefore concurrent editing of the same database file by multiple Database
  51. * instances (or with outside programs such as MS Access) <i>will generally
  52. * result in database file corruption</i>.
  53. *
  54. * @author James Ahlborn
  55. * @usage _general_class_
  56. */
  57. public interface Database extends Iterable<Table>, Closeable, Flushable
  58. {
  59. /** default value for the auto-sync value ({@code true}). this is slower,
  60. * but leaves more chance of a useable database in the face of failures.
  61. * @usage _general_field_
  62. */
  63. public static final boolean DEFAULT_AUTO_SYNC = true;
  64. /**
  65. * the default sort order for table columns.
  66. * @usage _intermediate_field_
  67. */
  68. public static final Table.ColumnOrder DEFAULT_COLUMN_ORDER =
  69. Table.ColumnOrder.DATA;
  70. /** system property which can be used to set the default TimeZone used for
  71. * date calculations.
  72. * @usage _general_field_
  73. */
  74. public static final String TIMEZONE_PROPERTY =
  75. "com.healthmarketscience.jackcess.timeZone";
  76. /** system property prefix which can be used to set the default Charset
  77. * used for text data (full property includes the JetFormat version).
  78. * @usage _general_field_
  79. */
  80. public static final String CHARSET_PROPERTY_PREFIX =
  81. "com.healthmarketscience.jackcess.charset.";
  82. /** system property which can be used to set the path from which classpath
  83. * resources are loaded (must end with a "/" if non-empty). Default value
  84. * is {@value com.healthmarketscience.jackcess.impl.DatabaseImpl#DEFAULT_RESOURCE_PATH}
  85. * if unspecified.
  86. * @usage _general_field_
  87. */
  88. public static final String RESOURCE_PATH_PROPERTY =
  89. "com.healthmarketscience.jackcess.resourcePath";
  90. /** (boolean) system property which can be used to indicate that the current
  91. * vm has a poor nio implementation (specifically for
  92. * {@code FileChannel.transferFrom})
  93. * @usage _intermediate_field_
  94. */
  95. public static final String BROKEN_NIO_PROPERTY =
  96. "com.healthmarketscience.jackcess.brokenNio";
  97. /** system property which can be used to set the default sort order for
  98. * table columns. Value should be one of {@link Table.ColumnOrder} enum
  99. * values.
  100. * @usage _intermediate_field_
  101. */
  102. public static final String COLUMN_ORDER_PROPERTY =
  103. "com.healthmarketscience.jackcess.columnOrder";
  104. /** system property which can be used to set the default enforcement of
  105. * foreign-key relationships. Defaults to {@code true}.
  106. * @usage _general_field_
  107. */
  108. public static final String FK_ENFORCE_PROPERTY =
  109. "com.healthmarketscience.jackcess.enforceForeignKeys";
  110. /** system property which can be used to set the default allow auto number
  111. * insert policy. Defaults to {@code false}.
  112. * @usage _general_field_
  113. */
  114. public static final String ALLOW_AUTONUM_INSERT_PROPERTY =
  115. "com.healthmarketscience.jackcess.allowAutoNumberInsert";
  116. /** system property which can be used to enable expression evaluation
  117. * (currently experimental). Defaults to {@code false}.
  118. * @usage _general_field_
  119. */
  120. public static final String ENABLE_EXPRESSION_EVALUATION_PROPERTY =
  121. "com.healthmarketscience.jackcess.enableExpressionEvaluation";
  122. /** system property which can be used to set the default date/Time type.
  123. * Value should be one of {@link DateTimeType} enum values.
  124. * @usage _general_field_
  125. */
  126. public static final String DATE_TIME_TYPE_PROPERTY =
  127. "com.healthmarketscience.jackcess.dateTimeType";
  128. /**
  129. * Enum which indicates which version of Access created the database.
  130. * @usage _general_class_
  131. */
  132. public enum FileFormat {
  133. /** A database which was created by MS Access 97 */
  134. V1997(".mdb"),
  135. /** A database which was most likely created programmatically (e.g. using
  136. windows ADOX) */
  137. GENERIC_JET4(".mdb"),
  138. /** A database which was created by MS Access 2000 */
  139. V2000(".mdb"),
  140. /** A database which was created by MS Access 2002/2003 */
  141. V2003(".mdb"),
  142. /** A database which was created by MS Access 2007 */
  143. V2007(".accdb"),
  144. /** A database which was created by MS Access 2010+ */
  145. V2010(".accdb"),
  146. /** A database which was created by MS Access 2016+ */
  147. V2016(".accdb"),
  148. /** A database which was created by MS Money */
  149. MSISAM(".mny");
  150. private final String _ext;
  151. private FileFormat(String ext) {
  152. _ext = ext;
  153. }
  154. /**
  155. * @return the file extension used for database files with this format.
  156. */
  157. public String getFileExtension() { return _ext; }
  158. @Override
  159. public String toString() {
  160. return name() + " [" + DatabaseImpl.getFileFormatDetails(this).getFormat() + "]";
  161. }
  162. }
  163. /**
  164. * Returns the File underlying this Database
  165. */
  166. public File getFile();
  167. /**
  168. * Returns the File underlying this Database
  169. */
  170. public Path getPath();
  171. /**
  172. * @return The names of all of the user tables
  173. * @usage _general_method_
  174. */
  175. public Set<String> getTableNames() throws IOException;
  176. /**
  177. * @return The names of all of the system tables (String). Note, in order
  178. * to read these tables, you must use {@link #getSystemTable}.
  179. * <i>Extreme care should be taken if modifying these tables
  180. * directly!</i>.
  181. * @usage _intermediate_method_
  182. */
  183. public Set<String> getSystemTableNames() throws IOException;
  184. /**
  185. * @return an unmodifiable Iterator of the user Tables in this Database.
  186. * @throws RuntimeIOException if an IOException is thrown by one of the
  187. * operations, the actual exception will be contained within
  188. * @throws ConcurrentModificationException if a table is added to the
  189. * database while an Iterator is in use.
  190. * @usage _general_method_
  191. */
  192. @Override
  193. public Iterator<Table> iterator();
  194. /**
  195. * @return a Stream using the default Iterator.
  196. */
  197. default public Stream<Table> stream() {
  198. return StreamSupport.stream(spliterator(), false);
  199. }
  200. /**
  201. * Convenience method for constructing a new TableIterableBuilder for this
  202. * cursor. A TableIterableBuilder provides a variety of options for more
  203. * flexible iteration of Tables.
  204. */
  205. public TableIterableBuilder newIterable();
  206. /**
  207. * @return an Iterable which returns an unmodifiable Iterator of the the
  208. * TableMetaData for all tables in this Database.
  209. * @throws RuntimeIOException if an IOException is thrown by one of the
  210. * operations, the actual exception will be contained within
  211. * @throws ConcurrentModificationException if a table is added to the
  212. * database while an Iterator is in use.
  213. * @usage _intermediate_method_
  214. */
  215. public Iterable<TableMetaData> newTableMetaDataIterable();
  216. /**
  217. * @return a Stream using the {@link #newTableMetaDataIterable}
  218. */
  219. default public Stream<TableMetaData> newTableMetaDataStream() {
  220. return StreamSupport.stream(
  221. newTableMetaDataIterable().spliterator(), false);
  222. }
  223. /**
  224. * @param name User table name (case-insensitive)
  225. * @return The Table, or null if it doesn't exist (or is a system table)
  226. * @usage _general_method_
  227. */
  228. public Table getTable(String name) throws IOException;
  229. /**
  230. * @param name Table name (case-insensitive), may be any table type
  231. * (i.e. includes system or linked tables).
  232. * @return The meta data for the table, or null if it doesn't exist
  233. * @usage _intermediate_method_
  234. */
  235. public TableMetaData getTableMetaData(String name) throws IOException;
  236. /**
  237. * Finds all the relationships in the database between the given tables.
  238. * @usage _intermediate_method_
  239. */
  240. public List<Relationship> getRelationships(Table table1, Table table2)
  241. throws IOException;
  242. /**
  243. * Finds all the relationships in the database for the given table.
  244. * @usage _intermediate_method_
  245. */
  246. public List<Relationship> getRelationships(Table table) throws IOException;
  247. /**
  248. * Finds all the relationships in the database in <i>non-system</i> tables.
  249. * <p>
  250. * Warning, this may load <i>all</i> the Tables (metadata, not data) in the
  251. * database which could cause memory issues.
  252. * @usage _intermediate_method_
  253. */
  254. public List<Relationship> getRelationships() throws IOException;
  255. /**
  256. * Finds <i>all</i> the relationships in the database, <i>including system
  257. * tables</i>.
  258. * <p>
  259. * Warning, this may load <i>all</i> the Tables (metadata, not data) in the
  260. * database which could cause memory issues.
  261. * @usage _intermediate_method_
  262. */
  263. public List<Relationship> getSystemRelationships()
  264. throws IOException;
  265. /**
  266. * Finds all the queries in the database.
  267. * @usage _intermediate_method_
  268. */
  269. public List<Query> getQueries() throws IOException;
  270. /**
  271. * Returns a reference to <i>any</i> available table in this access
  272. * database, including system tables.
  273. * <p>
  274. * Warning, this method is not designed for common use, only for the
  275. * occassional time when access to a system table is necessary. Messing
  276. * with system tables can strip the paint off your house and give your whole
  277. * family a permanent, orange afro. You have been warned.
  278. *
  279. * @param tableName Table name, may be a system table
  280. * @return The table, or {@code null} if it doesn't exist
  281. * @usage _intermediate_method_
  282. */
  283. public Table getSystemTable(String tableName) throws IOException;
  284. /**
  285. * @return the core properties for the database
  286. * @usage _general_method_
  287. */
  288. public PropertyMap getDatabaseProperties() throws IOException;
  289. /**
  290. * @return the summary properties for the database
  291. * @usage _general_method_
  292. */
  293. public PropertyMap getSummaryProperties() throws IOException;
  294. /**
  295. * @return the user-defined properties for the database
  296. * @usage _general_method_
  297. */
  298. public PropertyMap getUserDefinedProperties() throws IOException;
  299. /**
  300. * @return the current database password, or {@code null} if none set.
  301. * @usage _general_method_
  302. */
  303. public String getDatabasePassword() throws IOException;
  304. /**
  305. * Create a new table in this database
  306. * @param name Name of the table to create in this database
  307. * @param linkedDbName path to the linked database
  308. * @param linkedTableName name of the table in the linked database
  309. * @usage _general_method_
  310. */
  311. public void createLinkedTable(String name, String linkedDbName,
  312. String linkedTableName)
  313. throws IOException;
  314. /**
  315. * Flushes any current changes to the database file (and any linked
  316. * databases) to disk.
  317. * @usage _general_method_
  318. */
  319. @Override
  320. public void flush() throws IOException;
  321. /**
  322. * Close the database file (and any linked databases). A Database
  323. * <b>must</b> be closed after use or changes could be lost and the Database
  324. * file corrupted. A Database instance should be treated like any other
  325. * external resource which would be closed in a finally block (e.g. an
  326. * OutputStream or jdbc Connection).
  327. * @usage _general_method_
  328. */
  329. @Override
  330. public void close() throws IOException;
  331. /**
  332. * Gets the currently configured ErrorHandler (always non-{@code null}).
  333. * This will be used to handle all errors unless overridden at the Table or
  334. * Cursor level.
  335. * @usage _intermediate_method_
  336. */
  337. public ErrorHandler getErrorHandler();
  338. /**
  339. * Sets a new ErrorHandler. If {@code null}, resets to the
  340. * {@link ErrorHandler#DEFAULT}.
  341. * @usage _intermediate_method_
  342. */
  343. public void setErrorHandler(ErrorHandler newErrorHandler);
  344. /**
  345. * Gets the currently configured LinkResolver (always non-{@code null}).
  346. * This will be used to handle all linked database loading.
  347. * @usage _intermediate_method_
  348. */
  349. public LinkResolver getLinkResolver();
  350. /**
  351. * Sets a new LinkResolver. If {@code null}, resets to the
  352. * {@link LinkResolver#DEFAULT}.
  353. * @usage _intermediate_method_
  354. */
  355. public void setLinkResolver(LinkResolver newLinkResolver);
  356. /**
  357. * Returns an unmodifiable view of the currently loaded linked databases,
  358. * mapped from the linked database file name to the linked database. This
  359. * information may be useful for implementing a LinkResolver.
  360. * @usage _intermediate_method_
  361. */
  362. public Map<String,Database> getLinkedDatabases();
  363. /**
  364. * Returns {@code true} if this Database links to the given Table, {@code
  365. * false} otherwise.
  366. * @usage _general_method_
  367. */
  368. public boolean isLinkedTable(Table table) throws IOException;
  369. /**
  370. * Gets currently configured TimeZone (always non-{@code null} and aligned
  371. * with the ZoneId).
  372. * @usage _intermediate_method_
  373. */
  374. public TimeZone getTimeZone();
  375. /**
  376. * Sets a new TimeZone. If {@code null}, resets to the default value. Note
  377. * that setting the TimeZone will alter the ZoneId as well.
  378. * @usage _intermediate_method_
  379. */
  380. public void setTimeZone(TimeZone newTimeZone);
  381. /**
  382. * Gets currently configured ZoneId (always non-{@code null} and aligned
  383. * with the TimeZone).
  384. * @usage _intermediate_method_
  385. */
  386. public ZoneId getZoneId();
  387. /**
  388. * Sets a new ZoneId. If {@code null}, resets to the default value. Note
  389. * that setting the ZoneId will alter the TimeZone as well.
  390. * @usage _intermediate_method_
  391. */
  392. public void setZoneId(ZoneId newZoneId);
  393. /**
  394. * Gets currently configured Charset (always non-{@code null}).
  395. * @usage _intermediate_method_
  396. */
  397. public Charset getCharset();
  398. /**
  399. * Sets a new Charset. If {@code null}, resets to the default value.
  400. * @usage _intermediate_method_
  401. */
  402. public void setCharset(Charset newCharset);
  403. /**
  404. * Gets currently configured {@link Table.ColumnOrder} (always non-{@code
  405. * null}).
  406. * @usage _intermediate_method_
  407. */
  408. public Table.ColumnOrder getColumnOrder();
  409. /**
  410. * Sets a new Table.ColumnOrder. If {@code null}, resets to the default value.
  411. * @usage _intermediate_method_
  412. */
  413. public void setColumnOrder(Table.ColumnOrder newColumnOrder);
  414. /**
  415. * Gets current foreign-key enforcement policy.
  416. * @usage _intermediate_method_
  417. */
  418. public boolean isEnforceForeignKeys();
  419. /**
  420. * Sets a new foreign-key enforcement policy. If {@code null}, resets to
  421. * the default value.
  422. * @usage _intermediate_method_
  423. */
  424. public void setEnforceForeignKeys(Boolean newEnforceForeignKeys);
  425. /**
  426. * Gets current allow auto number insert policy. By default, jackcess does
  427. * not allow auto numbers to be inserted or updated directly (they are
  428. * always handled internally by the Table). Setting this policy to {@code
  429. * true} allows the caller to optionally set the value explicitly when
  430. * adding or updating rows (if a value is not provided, it will still be
  431. * handled internally by the Table). This value can be set database-wide
  432. * using {@link #setAllowAutoNumberInsert} and/or on a per-table basis using
  433. * {@link Table#setAllowAutoNumberInsert} (and/or on a jvm-wide using the
  434. * {@link #ALLOW_AUTONUM_INSERT_PROPERTY} system property). Note that
  435. * <i>enabling this feature should be done with care</i> to reduce the
  436. * chances of screwing up the database.
  437. *
  438. * @usage _intermediate_method_
  439. */
  440. public boolean isAllowAutoNumberInsert();
  441. /**
  442. * Sets the new auto number insert policy for the database (unless
  443. * overridden at the Table level). If {@code null}, resets to the default
  444. * value.
  445. * @usage _intermediate_method_
  446. */
  447. public void setAllowAutoNumberInsert(Boolean allowAutoNumInsert);
  448. /**
  449. * Gets the current expression evaluation policy. Expression evaluation is
  450. * currently an experimental feature, and is therefore disabled by default.
  451. */
  452. public boolean isEvaluateExpressions();
  453. /**
  454. * Sets the current expression evaluation policy. Expression evaluation is
  455. * currently an experimental feature, and is therefore disabled by default.
  456. * If {@code null}, resets to the default value.
  457. * @usage _intermediate_method_
  458. */
  459. public void setEvaluateExpressions(Boolean evaluateExpressions);
  460. /**
  461. * Gets currently configured ColumnValidatorFactory (always non-{@code null}).
  462. * @usage _intermediate_method_
  463. */
  464. public ColumnValidatorFactory getColumnValidatorFactory();
  465. /**
  466. * Sets a new ColumnValidatorFactory. If {@code null}, resets to the
  467. * default value. The configured ColumnValidatorFactory will be used to
  468. * create ColumnValidator instances on any <i>user</i> tables loaded from
  469. * this point onward (this will not be used for system tables).
  470. * @usage _intermediate_method_
  471. */
  472. public void setColumnValidatorFactory(ColumnValidatorFactory newFactory);
  473. /**
  474. * Returns the FileFormat of this database (which may involve inspecting the
  475. * database itself).
  476. * @throws IllegalStateException if the file format cannot be determined
  477. * @usage _general_method_
  478. */
  479. public FileFormat getFileFormat() throws IOException;
  480. /**
  481. * Returns the EvalConfig for configuring expression evaluation.
  482. */
  483. public EvalConfig getEvalConfig();
  484. /**
  485. * Gets the currently configured DateTimeType.
  486. * @usage _general_method_
  487. */
  488. public DateTimeType getDateTimeType();
  489. /**
  490. * Sets the DateTimeType. If {@code null}, resets to the default value.
  491. * @usage _general_method_
  492. */
  493. public void setDateTimeType(DateTimeType dateTimeType);
  494. }