]> source.dussan.org Git - jackcess.git/commitdiff
Ignore column validators for read-only dbs. This will avoid irrelevant failures...
authorJames Ahlborn <jtahlborn@yahoo.com>
Mon, 17 Dec 2018 21:39:40 +0000 (21:39 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Mon, 17 Dec 2018 21:39:40 +0000 (21:39 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1240 f203690c-595d-4dc9-a70b-905162fa7fd2

NOTICE.txt [new file with mode: 0644]
src/changes/changes.xml
src/main/java/com/healthmarketscience/jackcess/expr/package-info.java
src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java
src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java
src/main/java/com/healthmarketscience/jackcess/util/LinkResolver.java
src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java

diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644 (file)
index 0000000..bf7ce69
--- /dev/null
@@ -0,0 +1,5 @@
+Many of the financial functions have been originally copied from the Apache
+POI project (Apache Software Foundation) and the UCanAccess Project.  They
+have been then modified and adapted so that they are integrated with Jackcess,
+in a consistent manner.  The Apache POI and UCanAccess projects are licensed
+under Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.
index 74c82add71cb0339131c71c9115971deba6b7195..3d1160d3876799ac3b265c92299706b818a6d17d 100644 (file)
@@ -6,8 +6,26 @@
   <body>
     <release version="2.2.1" date="TBD">
       <action dev="jahlborn" type="update">
-        Implement IsNumeric function.  Add support for hex/oct integer
-        strings.
+        Implement the majority of the missing standard functions:
+        FormatCurrency, FormatDateTime, FormatNumber, FormatPercent, Val,
+        DateAdd, DateDiff, DatePart, MonthName, WeekdayName, DDB, IPmt, PPmt,
+        Rate, SLN, SYD, Format, Replace, StrConv.  (Note that the internal API
+        for the expr package has changed in an incompatible way.  However,
+        since the API is still experimental, this was deemed acceptable for a
+        minor version.).  Note that many of the financial functions were
+        copied and adpated from the Apache POI and UCanAccess projects (which
+        are both under the Apache License 2.0).
+      </action>
+      <action dev="jahlborn" type="update">
+        Implement more type coercion methods for expressions.  Add support for
+        hex/oct integer strings.  Add support for number strings with commas.
+        Add support for coercing numeric String to a date/time value.  Add
+        support for date/time values with implicit (current) year.
+      </action>
+      <action dev="jahlborn" type="fix" system="SourceForge2" issue="150">
+        Ignore column validators for read-only dbs.  This will avoid
+        irrelevant failures when reading databases which have invalid column
+        properties.
       </action>
     </release>
     <release version="2.2.0" date="2018-09-08"
index 28d9a868c68daa19dabadcac08c46e26e08479d9..6e4d5ab60a3530d63b201b928c61604d4cd580bd 100644 (file)
@@ -215,7 +215,7 @@ limitations under the License.
  *
  * <table border="1" width="25%" cellpadding="3" cellspacing="0">
  * <tr class="TableHeadingColor" align="left"><th>Function</th><th>Supported</th></tr>
- * <tr class="TableRowColor"><td>Format[$]</td><td></td></tr>
+ * <tr class="TableRowColor"><td>Format[$]</td><td>Partial</td></tr>
  * <tr class="TableRowColor"><td>InStr</td><td>Y</td></tr>
  * <tr class="TableRowColor"><td>InStrRev</td><td>Y</td></tr>
  * <tr class="TableRowColor"><td>LCase[$]</td><td>Y</td></tr>
index 6d237b41d82da3f16d66ded98d4807d98bdb69a9..0016687482621de47732f4c4c6540ba078c3ffb9 100644 (file)
@@ -491,6 +491,12 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
   }
 
   void initColumnValidator() throws IOException {
+
+    if(getDatabase().isReadOnly()) {
+      // validators are irrelevant for read-only databases
+      return;
+    }
+
     // first initialize any "external" (user-defined) validator
     setColumnValidator(null);
 
index 6831e99c7e53c50d3426cff9359a1a94991d806d..bb74bba12edd468d5467d5562f5e8fabc23ce6cc 100644 (file)
@@ -255,6 +255,8 @@ public class DatabaseImpl implements Database
   private final File _file;
   /** the simple name of the database */
   private final String _name;
+  /** whether or not this db is read-only */
+  private final boolean _readOnly;
   /** Buffer to hold database pages */
   private ByteBuffer _buffer;
   /** ID of the Tables system object */
@@ -399,7 +401,8 @@ public class DatabaseImpl implements Database
       }
 
       DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync,
-                                         null, charset, timeZone, provider);
+                                         null, charset, timeZone, provider,
+                                         readOnly);
       success = true;
       return db;
 
@@ -458,7 +461,8 @@ public class DatabaseImpl implements Database
       transferDbFrom(channel, getResourceAsStream(details.getEmptyFilePath()));
       channel.force(true);
       DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync,
-                                         fileFormat, charset, timeZone, null);
+                                         fileFormat, charset, timeZone, null,
+                                         false);
       success = true;
       return db;
     } finally {
@@ -510,11 +514,13 @@ public class DatabaseImpl implements Database
    */
   protected DatabaseImpl(File file, FileChannel channel, boolean closeChannel,
                          boolean autoSync, FileFormat fileFormat, Charset charset,
-                         TimeZone timeZone, CodecProvider provider)
+                         TimeZone timeZone, CodecProvider provider,
+                         boolean readOnly)
     throws IOException
   {
     _file = file;
     _name = getName(file);
+    _readOnly = readOnly;
     _format = JetFormat.getFormat(channel);
     _charset = ((charset == null) ? getDefaultCharset(_format) : charset);
     _columnOrder = getDefaultColumnOrder();
@@ -543,6 +549,10 @@ public class DatabaseImpl implements Database
     return _name;
   }
 
+  public boolean isReadOnly() {
+    return _readOnly;
+  }
+
   /**
    * @usage _advanced_method_
    */
index 564376659229a3e64d0e2702f2b3f72b30b480a0..74856aac68abab20a40870fa7dad538571e9386c 100644 (file)
@@ -425,7 +425,7 @@ public class DefaultTextFunctions
     }
   });
 
-  public static final Function FORMAT = registerFunc(new FuncVar("Format", 1, 4) {
+  public static final Function FORMAT = registerStringFunc(new FuncVar("Format", 1, 4) {
     @Override
     protected Value evalVar(EvalContext ctx, Value[] params) {
 
@@ -441,11 +441,11 @@ public class DefaultTextFunctions
       String fmtStr = params[1].getAsString(ctx);
       int firstDay = DefaultDateFunctions.getFirstDayParam(ctx, params, 2);
       int firstWeekType = DefaultDateFunctions.getFirstWeekTypeParam(ctx, params, 3);
-      
+
       return FormatUtil.format(ctx, expr, fmtStr, firstDay, firstWeekType);
     }
   });
-    
+
   private static String nchars(int num, char c) {
     StringBuilder sb = new StringBuilder(num);
     nchars(sb, num, c);
@@ -457,7 +457,7 @@ public class DefaultTextFunctions
       sb.append(c);
     }
   }
-  
+
   private static String trim(String str, boolean doLeft, boolean doRight) {
     int start = 0;
     int end = str.length();
index 7992d71dfbae201896c6aa29f8ea9cb817fcf1b3..fce528945d26382e082d878651af04ce9e9c3141 100644 (file)
@@ -117,28 +117,31 @@ public abstract class CustomLinkResolver implements LinkResolver
    * <pre>
    *   // attempt to load the linkeeFileName as a custom file
    *   Object customFile = loadCustomFile(linkerDb, linkeeFileName);
-   *   
+   *
    *   if(customFile != null) {
    *     // this is a custom file, create and return relevant temp db
    *     return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(),
    *                         getDefaultTempDirectory());
    *   }
-   *   
+   *
    *   // not a custmom file, load using the default behavior
    *   return LinkResolver.DEFAULT.resolveLinkedDatabase(linkerDb, linkeeFileName);
    * </pre>
-   * 
+   *
    * @see #loadCustomFile
    * @see #createTempDb
    * @see LinkResolver#DEFAULT
    */
   public Database resolveLinkedDatabase(Database linkerDb, String linkeeFileName)
-    throws IOException 
+    throws IOException
   {
     Object customFile = loadCustomFile(linkerDb, linkeeFileName);
     if(customFile != null) {
-      return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(), 
-                          getDefaultTempDirectory());
+      // if linker is read-only, open linkee read-only
+      boolean readOnly = ((linkerDb instanceof DatabaseImpl) ?
+                          ((DatabaseImpl)linkerDb).isReadOnly() : false);
+      return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(),
+                          getDefaultTempDirectory(), readOnly);
     }
     return LinkResolver.DEFAULT.resolveLinkedDatabase(linkerDb, linkeeFileName);
   }
@@ -157,8 +160,9 @@ public abstract class CustomLinkResolver implements LinkResolver
    *
    * @return the temp db for holding the linked table info
    */
-  protected Database createTempDb(Object customFile, FileFormat format, 
-                                  boolean inMemory, File tempDir)
+  protected Database createTempDb(Object customFile, FileFormat format,
+                                  boolean inMemory, File tempDir,
+                                  boolean readOnly)
     throws IOException
   {
     File dbFile = null;
@@ -178,8 +182,8 @@ public abstract class CustomLinkResolver implements LinkResolver
       }
 
       TempDatabaseImpl.initDbChannel(channel, format);
-      TempDatabaseImpl db = new TempDatabaseImpl(this, customFile, dbFile, 
-                                                 channel, format);
+      TempDatabaseImpl db = new TempDatabaseImpl(this, customFile, dbFile,
+                                                 channel, format, readOnly);
       success = true;
       return db;
 
@@ -203,7 +207,7 @@ public abstract class CustomLinkResolver implements LinkResolver
       ByteUtil.closeQuietly((Closeable)customFile);
     }
   }
-  
+
   /**
    * Called by {@link #resolveLinkedDatabase} to determine whether the
    * linkeeFileName should be treated as a custom file (thus utiliziing a temp
@@ -252,21 +256,22 @@ public abstract class CustomLinkResolver implements LinkResolver
     private final Object _customFile;
 
     protected TempDatabaseImpl(CustomLinkResolver resolver, Object customFile,
-                               File file, FileChannel channel, 
-                               FileFormat fileFormat)
+                               File file, FileChannel channel,
+                               FileFormat fileFormat, boolean readOnly)
       throws IOException
     {
-      super(file, channel, true, false, fileFormat, null, null, null);
+      super(file, channel, true, false, fileFormat, null, null, null,
+            readOnly);
       _resolver = resolver;
       _customFile = customFile;
     }
 
     @Override
-    protected TableImpl getTable(String name, boolean includeSystemTables) 
-      throws IOException 
+    protected TableImpl getTable(String name, boolean includeSystemTables)
+      throws IOException
     {
       TableImpl table = super.getTable(name, includeSystemTables);
-      if((table == null) && 
+      if((table == null) &&
          _resolver.loadCustomTable(this, _customFile, name)) {
         table = super.getTable(name, includeSystemTables);
       }
index ebb1bbd42534ddafc8ae17494e0b6e6b14ceb84c..5310449dc424210b4fcfaa05498c7795c51b7774 100644 (file)
@@ -21,6 +21,7 @@ import java.io.IOException;
 
 import com.healthmarketscience.jackcess.Database;
 import com.healthmarketscience.jackcess.DatabaseBuilder;
+import com.healthmarketscience.jackcess.impl.DatabaseImpl;
 
 /**
  * Resolver for linked databases.
@@ -28,7 +29,7 @@ import com.healthmarketscience.jackcess.DatabaseBuilder;
  * @author James Ahlborn
  * @usage _intermediate_class_
  */
-public interface LinkResolver 
+public interface LinkResolver
 {
   /**
    * default link resolver used if none provided
@@ -39,7 +40,11 @@ public interface LinkResolver
                                             String linkeeFileName)
         throws IOException
       {
-        return DatabaseBuilder.open(new File(linkeeFileName));
+        // if linker is read-only, open linkee read-only
+        boolean readOnly = ((linkerDb instanceof DatabaseImpl) ?
+                            ((DatabaseImpl)linkerDb).isReadOnly() : false);
+        return new DatabaseBuilder(new File(linkeeFileName))
+          .setReadOnly(readOnly).open();
       }
     };
 
index 31a885351ffedbe692731544da0f1c2a06ef4458..87f8e6fcfa5142c7d8e986fcfa4db3a983ca2709 100644 (file)
@@ -55,7 +55,7 @@ public class CustomLinkResolverTest extends TestCase
       Table t1 = db.getTable("Table1");
       assertNotNull(t1);
       assertNotSame(db, t1.getDatabase());
-      
+
       assertTable(createExpectedTable(createExpectedRow("id", 0,
                                                         "data1", "row0"),
                                       createExpectedRow("id", 1,
@@ -101,7 +101,7 @@ public class CustomLinkResolverTest extends TestCase
         Database linkerDb, String linkeeFileName) throws IOException
     {
       return (("testFile1.txt".equals(linkeeFileName) ||
-               "testFile2.txt".equals(linkeeFileName)) ? 
+               "testFile2.txt".equals(linkeeFileName)) ?
               linkeeFileName : null);
     }
 
@@ -121,7 +121,7 @@ public class CustomLinkResolverTest extends TestCase
         for(int i = 0; i < 3; ++i) {
           t.addRow(i, "row" + i);
         }
-        
+
         return true;
 
       } else if("OtherTable2".equals(tableName)) {
@@ -135,7 +135,7 @@ public class CustomLinkResolverTest extends TestCase
         for(int i = 3; i < 6; ++i) {
           t.addRow(i, "row" + i);
         }
-        
+
         return true;
 
       } else if("Table4".equals(tableName)) {
@@ -149,11 +149,13 @@ public class CustomLinkResolverTest extends TestCase
 
     @Override
     protected Database createTempDb(Object customFile, FileFormat format,
-                                    boolean inMemory, File tempDir)
+                                    boolean inMemory, File tempDir,
+                                    boolean readOnly)
       throws IOException
     {
       inMemory = "testFile1.txt".equals(customFile);
-      return super.createTempDb(customFile, format, inMemory, tempDir);
+      return super.createTempDb(customFile, format, inMemory, tempDir,
+                                readOnly);
     }
   }
 }