/**
   * Opens this database. The database should be opened after construction. or reopened by the
   * close(int closemode) method during a "shutdown compact". Closes the log if there is an error.
   */
  void reopen() {

    boolean isNew = false;

    setState(DATABASE_OPENING);

    try {
      nameManager = new HsqlNameManager(this);
      granteeManager = new GranteeManager(this);
      userManager = new UserManager(this);
      schemaManager = new SchemaManager(this);
      persistentStoreCollection = new PersistentStoreCollectionDatabase(this);
      isReferentialIntegrity = true;
      sessionManager = new SessionManager(this);
      collation = collation.newDatabaseInstance();
      dbInfo = DatabaseInformation.newDatabaseInformation(this);
      txManager = new TransactionManager2PL(this);

      lobManager.createSchema();
      sessionManager.getSysLobSession().setSchema(SqlInvariants.LOBS_SCHEMA);
      schemaManager.setSchemaChangeTimestamp();
      schemaManager.createSystemTables();

      // completed metadata
      logger.open();

      isNew = logger.isNewDatabase;

      if (isNew) {
        String username = urlProperties.getProperty("user", "SA");
        String password = urlProperties.getProperty("password", "");

        userManager.createFirstUser(username, password);
        schemaManager.createPublicSchema();
        logger.checkpoint(false);
      }

      lobManager.open();
      dbInfo.setWithContent(true);

      checkpointRunner = new CheckpointRunner();
      timeoutRunner = new TimeoutRunner();
    } catch (Throwable e) {
      logger.close(Database.CLOSEMODE_IMMEDIATELY);
      logger.releaseLock();
      setState(DATABASE_SHUTDOWN);
      clearStructures();
      DatabaseManager.removeDatabase(this);

      if (!(e instanceof HsqlException)) {
        e = Error.error(ErrorCode.GENERAL_ERROR, e);
      }

      logger.logSevereEvent("could not reopen database", e);

      throw (HsqlException) e;
    }

    setState(DATABASE_ONLINE);
  }
  /**
   * Constructs a new Database object.
   *
   * @param type is the type of the database: "mem", "file", "res"
   * @param path is the fiven path to the database files
   * @param name is the combination of type and canonical path
   * @param props property overrides placed on the connect URL
   * @exception HsqlException if the specified name and path combination is illegal or unavailable,
   *     or the database files the name and path resolves to are in use by another process
   */
  Database(String type, String path, String name, HsqlProperties props) throws HsqlException {

    urlProperties = props;

    setState(Database.DATABASE_SHUTDOWN);

    sName = name;
    sType = type;
    sPath = path;

    if (sType == DatabaseURL.S_RES) {
      filesInJar = true;
      filesReadOnly = true;
    }

    // does not need to be done more than once
    try {
      classLoader = getClass().getClassLoader();
    } catch (Exception e) {

      // strict security policy:  just use the system/boot loader
      classLoader = null;
    }

    // [email protected] - changed to file access api
    String fileaccess_class_name = (String) urlProperties.getProperty("fileaccess_class_name");

    if (fileaccess_class_name != null) {
      String storagekey = urlProperties.getProperty("storage_key");

      try {
        Class fileAccessClass = null;
        try {
          ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
          fileAccessClass = classLoader.loadClass(fileaccess_class_name);
        } catch (ClassNotFoundException e) {
          fileAccessClass = Class.forName(fileaccess_class_name);
        }
        Constructor constructor = fileAccessClass.getConstructor(new Class[] {Object.class});

        fileaccess = (FileAccess) constructor.newInstance(new Object[] {storagekey});
        isStoredFileAccess = true;
      } catch (Exception e) {
        throw Trace.error(Trace.INVALID_FILE_ACCESS_CLASS, new Object[] {e.toString()});
      }
    } else {
      fileaccess = FileUtil.getDefaultInstance();
    }

    shutdownOnNoConnection = urlProperties.getProperty("shutdown", "false").equals("true");
    logger = new Logger();
    compiledStatementManager = new CompiledStatementManager(this);
  }
  /**
   * Translates the legacy default database form: database=... to the 1.7.2 form: database.0=...
   *
   * @param p The properties object upon which to perform the translation
   */
  public static void translateDefaultDatabaseProperty(HsqlProperties p) {

    if (p == null) {
      return;
    }

    String defaultdb = p.getProperty(SC_KEY_DATABASE);

    if (defaultdb != null) {
      p.setProperty(SC_KEY_DATABASE + ".0", defaultdb);
    }
  }
  /**
   * Translates null or zero length value for address key to the special value
   * ServerConstants.SC_DEFAULT_ADDRESS which causes ServerSockets to be constructed without
   * specifying an InetAddress.
   *
   * @param p The properties object upon which to perform the translation
   */
  public static void translateAddressProperty(HsqlProperties p) {

    if (p == null) {
      return;
    }

    String address = p.getProperty(SC_KEY_ADDRESS);

    if (StringUtil.isEmpty(address)) {
      p.setProperty(SC_KEY_ADDRESS, SC_DEFAULT_ADDRESS);
    }
  }
  /**
   * Retrieves a new HsqlProperties object, if possible, loaded from the specified file.
   *
   * @param path the file's path, without the .properties extention (which is added automatically)
   * @return a new properties object loaded from the specified file
   */
  public static HsqlProperties getPropertiesFromFile(String path) {

    if (StringUtil.isEmpty(path)) {
      return null;
    }

    HsqlProperties p = new HsqlProperties(path);

    try {
      p.load();
    } catch (Exception e) {
    }

    return p;
  }
  /**
   * Opens this database. The database should be opened after construction. or reopened by the
   * close(int closemode) method during a "shutdown compact". Closes the log if there is an error.
   */
  void reopen() throws HsqlException {

    boolean isNew;

    setState(DATABASE_OPENING);

    try {
      databaseProperties = new HsqlDatabaseProperties(this);
      isNew = !DatabaseURL.isFileBasedDatabaseType(sType) || !databaseProperties.checkFileExists();

      if (isNew && urlProperties.isPropertyTrue("ifexists")) {
        throw Trace.error(Trace.DATABASE_NOT_EXISTS, sName);
      }

      databaseProperties.load();
      databaseProperties.setURLProperties(urlProperties);
      compiledStatementManager.reset();

      nameManager = new HsqlNameManager();
      granteeManager = new GranteeManager(this);
      userManager = new UserManager(this);
      hAlias = Library.getAliasMap();
      schemaManager = new SchemaManager(this);
      bReferentialIntegrity = true;
      sessionManager = new SessionManager(this);
      txManager = new TransactionManager(this);
      collation = new Collation();
      dbInfo = DatabaseInformation.newDatabaseInformation(this);

      databaseProperties.setDatabaseVariables();

      if (DatabaseURL.isFileBasedDatabaseType(sType)) {
        logger.openLog(this);
      }

      if (isNew) {
        sessionManager
            .getSysSession()
            .sqlExecuteDirectNoPreChecks("CREATE USER SA PASSWORD \"\" ADMIN");
        logger.synchLogForce();
      }

      dbInfo.setWithContent(true);
    } catch (Throwable e) {
      logger.closeLog(Database.CLOSEMODE_IMMEDIATELY);
      logger.releaseLock();
      setState(DATABASE_SHUTDOWN);
      clearStructures();
      DatabaseManager.removeDatabase(this);

      if (!(e instanceof HsqlException)) {
        e = Trace.error(Trace.GENERAL_ERROR, e.toString());
      }

      throw (HsqlException) e;
    }

    setState(DATABASE_ONLINE);
  }
  /**
   * Tranlates unspecified no_system_exit property to false, the default typically required when a
   * Server is started from the command line.
   *
   * @param p The properties object upon which to perform the translation
   */
  public static void translateDefaultNoSystemExitProperty(HsqlProperties p) {

    if (p == null) {
      return;
    }

    p.setPropertyIfNotExists(SC_KEY_NO_SYSTEM_EXIT, "false");
  }
  /**
   * Constructs a new Database object.
   *
   * @param type is the type of the database: "mem:", "file:", "res:"
   * @param path is the given path to the database files
   * @param canonicalPath is the canonical path
   * @param props property overrides placed on the connect URL
   * @exception HsqlException if the specified name and path combination is illegal or unavailable,
   *     or the database files the name and path resolves to are in use by another process
   */
  Database(String type, String path, String canonicalPath, HsqlProperties props) {

    setState(Database.DATABASE_SHUTDOWN);

    this.databaseType = type;
    this.path = path;
    this.canonicalPath = canonicalPath;
    this.urlProperties = props;

    if (databaseType == DatabaseURL.S_RES) {
      filesInJar = true;
      filesReadOnly = true;
    }

    logger = new Logger(this);
    shutdownOnNoConnection = urlProperties.isPropertyTrue(HsqlDatabaseProperties.url_shutdown);
    recoveryMode = urlProperties.getIntegerProperty(HsqlDatabaseProperties.url_recover, 0);
    lobManager = new LobManager(this);
  }
  @Override
  protected void before() throws Throwable {
    super.before();

    File hsqlHome = new File("target/temporary/hsqldb/" + name);
    if (hsqlHome.exists()) {
      hsqlHome.delete();
    }
    hsqlHome.mkdirs();

    String dbHome = "file:" + hsqlHome.getAbsolutePath();

    HsqlProperties p = new HsqlProperties();
    p.setProperty("server.database.0", dbHome);
    p.setProperty("server.dbname.0", name);
    p.setProperty("server.port", port);
    server = new Server();
    server.setProperties(p);
    server.setLogWriter(new PrintWriter(System.out));
    server.setErrWriter(new PrintWriter(System.err));
    server.start();
  }
Beispiel #10
0
  public static void main(String[] arg) {

    boolean webserver;
    String driver = "org.hsqldb.jdbcDriver";
    String url;
    String user;
    String password;
    int port;
    String defaulturl;
    String shutdownarg;

    if (arg.length > 0) {
      String p = arg[0];

      if ((p != null) && p.startsWith("-?")) {
        printHelp();

        return;
      }
    }

    HsqlProperties props = HsqlProperties.argArrayToProps(arg, "server");

    webserver = props.isPropertyTrue("server.webserver", false);
    defaulturl = webserver ? "jdbc:hsqldb:http://localhost" : "jdbc:hsqldb:hsql://localhost";

    int defaultport = webserver ? 80 : 9001;

    port = props.getIntegerProperty("server.port", defaultport);
    url = props.getProperty("server.url", defaulturl + ":" + port);
    user = props.getProperty("server.user", "sa");
    password = props.getProperty("server.password", "");
    shutdownarg = props.getProperty("server.shutdownarg", "");

    try {
      Class.forName(driver); // Load the driver

      Connection connection = DriverManager.getConnection(url, user, password);
      Statement statement = connection.createStatement();

      // can use SHUTDOWN COMPACT or SHUTDOWN IMMEDIATELY
      statement.execute("SHUTDOWN " + shutdownarg);
    } catch (ClassNotFoundException cnfe) {
      System.err.println(cnfe); // Driver not found
    } catch (SQLException sqle) {
      System.err.println(sqle); // error connection to database
    }
  }
 /**
  * Specifically, this opens a mem-only DB, populates it, starts a HyperSQL Server to server it,
  * and opens network JDBC Connection "netConn" to it,
  *
  * <p>Invoked before each test*() invocation by JUnit.
  */
 protected void setUp() {
   try {
     Connection setupConn = DriverManager.getConnection("jdbc:hsqldb:mem:test", "SA", "");
     setupConn.setAutoCommit(false);
     Statement st = setupConn.createStatement();
     st.executeUpdate("SET PASSWORD 'sapwd'");
     populate(st);
     st.close();
     setupConn.commit();
     setupConn.close();
   } catch (SQLException se) {
     throw new RuntimeException("Failed to set up in-memory database", se);
   }
   try {
     server = new Server();
     HsqlProperties properties = new HsqlProperties();
     if (System.getProperty("VERBOSE") == null) {
       server.setLogWriter(null);
       server.setErrWriter(null);
     } else {
       properties.setProperty("server.silent", "false");
       properties.setProperty("server.trace", "true");
     }
     properties.setProperty("server.database.0", "mem:test");
     properties.setProperty("server.dbname.0", "");
     properties.setProperty("server.port", AbstractTestOdbc.portString);
     server.setProperties(properties);
     server.start();
     try {
       Thread.sleep(1000);
     } catch (InterruptedException ie) {
     }
   } catch (Exception e) {
     throw new RuntimeException("Failed to set up in-memory database", e);
   }
   if (server.getState() != ServerConstants.SERVER_STATE_ONLINE) {
     throw new RuntimeException("Server failed to start up");
   }
   try {
     netConn = DriverManager.getConnection("jdbc:odbc:" + dsnName, "SA", "sapwd");
     // netConn.setAutoCommit(false);
   } catch (SQLException se) {
     if (se.getMessage().indexOf("No suitable driver") > -1) {
       throw new RuntimeException(
           "You must install the native library for Sun's jdbc:odbc " + "JDBC driver");
     }
     if (se.getMessage().indexOf("Data source name not found") > -1) {
       throw new RuntimeException(
           "You must configure ODBC DSN '"
               + dsnName
               + "' (you may change the name and/or port by setting Java "
               + "system properties 'test.hsqlodbc.port' or "
               + "'test.hsqlodbc.dsnname'");
     }
     throw new RuntimeException("Failed to set up JDBC/ODBC network connection", se);
   }
 }
  public void testHsqldbUrls() {

    HsqlProperties props;

    DatabaseURL.parseURL(
        "JDBC:hsqldb:hsql://myhost:1777/mydb;filepath=c:/myfile/database/db", true, false);
    DatabaseURL.parseURL("JDBC:hsqldb:../data/mydb.db", true, false);
    DatabaseURL.parseURL("JDBC:hsqldb:../data/mydb.db;ifexists=true", true, false);
    DatabaseURL.parseURL("JDBC:hsqldb:HSQL://localhost:9000/mydb", true, false);
    DatabaseURL.parseURL(
        "JDBC:hsqldb:Http://localhost:8080/servlet/org.hsqldb.Servlet/mydb;get_column_names=true",
        true,
        false);
    DatabaseURL.parseURL("JDBC:hsqldb:Http://localhost/servlet/org.hsqldb.Servlet/", true, false);
    DatabaseURL.parseURL("JDBC:hsqldb:hsql://myhost", true, false);

    props =
        DatabaseURL.parseURL(
            "jdbc:hsqldb:res://com.anorg.APath;hsqldb.crypt_provider=org.crypt.Provider",
            true,
            false);

    assertEquals(props.getProperty("hsqldb.crypt_provider"), "org.crypt.Provider");
    assertEquals(props.getProperty("database"), "//com.anorg.APath");

    System.setProperty("mypath", "/opt/mydir");
    props = DatabaseURL.parseURL("jdbc:hsqldb:file:${mypath}/mydata", true, false);

    assertEquals("/opt/mydir/mydata", props.getProperty("database"));

    props =
        DatabaseURL.parseURL(
            "JDBC:hsqldb:hsql://localhost:9000/mydb;file:data/hsqldb/XYZTEST;hsqldb.default_table_type=cached",
            true,
            false);
  }
  /**
   * Initializes this jdbcResultSetMetaData object from the specified Result and HsqlProperties
   * objects.
   *
   * @param r the Result object from which to initialize this jdbcResultSetMetaData object
   * @param props the HsqlProperties object from which to initialize this jdbcResultSetMetaData
   *     object
   * @throws SQLException if a database access error occurs
   */
  void init(Result r, HsqlProperties props) throws SQLException {

    jdbcColumnMetaData cmd;
    int type;
    Result.ResultMetaData rmd;

    if (r == null) {
      throw Util.sqlException(Trace.GENERAL_ERROR, Trace.JDBC_NO_RESULT_SET, null);
    }

    if (r.mode != ResultConstants.DATA) {

      // implied: columnCount = 0;
      return;
    }

    columnCount = r.getColumnCount();

    // fredt -  props is null for internal connections, so always use the default behaviour in this
    // case
    useColumnName = props == null ? true : props.isPropertyTrue("get_column_name");
    columnMetaData = new jdbcColumnMetaData[columnCount];
    rmd = r.metaData;

    for (int i = 0; i < columnCount; i++) {
      cmd = new jdbcColumnMetaData();
      columnMetaData[i] = cmd;

      // Typically, these null checks are not needed, but as
      // above, it is not _guaranteed_ that these values
      // will be non-null.   So, it is better to do the work
      // here than have to perform checks and conversions later.
      cmd.catalogName = rmd.catalogNames[i] == null ? "" : rmd.catalogNames[i];
      cmd.schemaName = rmd.schemaNames[i] == null ? "" : rmd.schemaNames[i];
      cmd.tableName = rmd.tableNames[i] == null ? "" : rmd.tableNames[i];
      cmd.columnName = rmd.colNames[i] == null ? "" : rmd.colNames[i];
      cmd.columnLabel = rmd.colLabels[i] == null ? "" : rmd.colLabels[i];
      cmd.columnType = rmd.colTypes[i];
      cmd.columnTypeName = Types.getTypeString(cmd.columnType);
      cmd.isWritable = rmd.isWritable[i];
      cmd.isReadOnly = !cmd.isWritable;

      // default: cmd.isDefinitelyWritable = false;
      cmd.isAutoIncrement = rmd.isIdentity[i];
      cmd.isNullable = rmd.colNullable[i];
      type = cmd.columnType;
      cmd.columnClassName = rmd.classNames[i];

      if (cmd.columnClassName == null || cmd.columnClassName.length() == 0) {
        cmd.columnClassName = Types.getColStClsName(type);
      }

      // Some tools, such as PowerBuilder, require that (for char and
      // varchar types, at any rate) getMaxDisplaySize returns a value
      // _at least_ as large as the length of the longest value in this
      // column of the result set, or else an internal error will occur
      // at retrieve time the instant a longer value is fetched.
      //
      // org.hsqldb.Types has been patched to retrieve, by default, either
      // a large-but-reasonable value or a value defined through system
      // properties that is expected to be unlikely to cause problems in
      // the majority of cases.
      if (Types.acceptsPrecisionCreateParam(type)) {
        if (rmd.colSizes[i] == 0) {
          cmd.columnDisplaySize = Types.getMaxDisplaySize(type);
        } else {
          cmd.columnDisplaySize = rmd.colSizes[i];

          if (Types.acceptsScaleCreateParam(type)) {
            if (rmd.colScales[i] != 0) {
              cmd.columnDisplaySize += (1 + rmd.colScales[i]);
            }
          }
        }
      } else {
        cmd.columnDisplaySize = Types.getMaxDisplaySize(type);
      }

      if (Types.isNumberType(type) && Types.acceptsPrecisionCreateParam(type)) {
        cmd.precision = rmd.colSizes[i];

        if (cmd.precision == 0) {
          cmd.precision = Types.getPrecision(type);
        }
      } else {
        cmd.precision = Types.getPrecision(type);
      }

      // Without a non-zero scale value, some (legacy only?) tools will
      // simply truncate digits to the right of the decimal point when
      // retrieving values from the result set. The measure below can
      // help, but currently only as long as one is connected to an
      // embedded instance at design time, not via a network connection.
      if (Types.acceptsScaleCreateParam(type)) {
        cmd.scale = rmd.colScales[i];
      }

      Boolean iua = Types.isUnsignedAttribute(type);

      cmd.isSigned = iua != null && !iua.booleanValue();

      Boolean ics = Types.isCaseSensitive(type);

      cmd.isCaseSensitive = ics != null && ics.booleanValue();
      cmd.isSearchable = Types.isSearchable(type);
    }
  }
  /**
   * Retrieves a new default properties object for a server of the specified protocol
   *
   * @return a new default properties object
   */
  public static HsqlProperties newDefaultProperties(int protocol) {

    HsqlProperties p = new HsqlProperties();

    p.setProperty(SC_KEY_AUTORESTART_SERVER, SC_DEFAULT_SERVER_AUTORESTART);
    p.setProperty(SC_KEY_ADDRESS, SC_DEFAULT_ADDRESS);
    p.setProperty(SC_KEY_DATABASE + "." + 0, SC_DEFAULT_DATABASE);
    p.setProperty(SC_KEY_DBNAME + "." + 0, "");
    p.setProperty(SC_KEY_NO_SYSTEM_EXIT, SC_DEFAULT_NO_SYSTEM_EXIT);

    boolean isTls = SC_DEFAULT_TLS;

    try {
      isTls = System.getProperty("javax.net.ssl.keyStore") != null;
    } catch (Exception e) {
    }

    p.setProperty(SC_KEY_PORT, getDefaultPort(protocol, isTls));
    p.setProperty(SC_KEY_SILENT, SC_DEFAULT_SILENT);
    p.setProperty(SC_KEY_TLS, isTls);
    p.setProperty(SC_KEY_TRACE, SC_DEFAULT_TRACE);
    p.setProperty(SC_KEY_WEB_DEFAULT_PAGE, SC_DEFAULT_WEB_PAGE);
    p.setProperty(SC_KEY_WEB_ROOT, SC_DEFAULT_WEB_ROOT);

    return p;
  }