More responses inline...

On 11/15/18 8:09 AM, Alex O'Ree wrote:
Thanks Rick

I also noticed that the wording and ordering of limit and offset for select statements is way different in derby.
Postgres style: select * from table limit 3 offset 5
Derby: select * from table offset 5 rows fetch next 3 rows only
Right. Derby uses the SQL Standard syntax. PostgreSQL uses the popular limit/offset syntax which never made it into the Standard. The JDBC limit/offset escape syntax is supposed to paper over this divergence of PostgreSQL and MySQL from the Standard. But it sounds as though you had some difficulty getting Derby's JDBC escape syntax to work for you.

Next issue I ran into was that I have tons of insert statements that read like this (postgres style) insert into table (column1, column2) values ('asd', 'xyz') on conflict do nothing;

An insert statement like this is used in a batched prepared statement. Overall goal is to insert everything and when there is a primary key collision, just ignore it. In postgres, any failure will cause the whole batch to abort. Is there a derby equivalent to this? I did run across this merge jira which may solve the problem. https://issues.apache.org/jira/browse/DERBY-3155 but is that the only solution?
Right. PostgreSQL and MySQL implemented their own, idiosyncratic UPSERT syntax. Derby uses the Standard MERGE syntax for this problem.

MERGE is a complicated statement and Derby's implementation is not complete. See http://db.apache.org/derby/docs/10.14/ref/rrefsqljmerge.html. Unfortunately, Derby does not support VALUES clauses in the USING clause of the MERGE statement. The following, admittedly awkward workarounds may help you:

o Use a temporary table as the driving relation of the MERGE statement.

o Use a table function as the driving relation of the MERGE statement. See http://db.apache.org/derby/docs/10.14/devguide/cdevspecialtabfuncs.html.

Here is a script which shows these workarounds in action:

connect 'jdbc:derby:memory:db;create=true';

-- using a temp table

create table t1(a varchar(10), b varchar(10));

declare global temporary table session.s1 (a varchar(10), b varchar(10)) not 
logged;

autocommit off;

insert into session.s1 values ('abc', 'def');

merge into t1 t

using session.s1 s

on t.a = s.a

when not matched then insert (a, b) values (s.a, s.b)

;

commit;

select * from t1;

-- using a table function

create function twoStringPassthrough(a varchar(32672), b varchar (32672))

returns table (a varchar(32672), b varchar (32672))

language java

parameter style derby_jdbc_result_set

no sql

external name 'TwoStringArgPassthrough.passthrough';

merge into t1 t

using table(twoStringPassthrough('ghi', 'jkl')) s

on t.a = s.a

when not matched then insert (a, b) values (s.a, s.b)

;

commit;

select * from t1;



Here is the source code for the table function:

import java.sql.SQLException;

import org.apache.derby.vti.StringColumnVTI;

public class TwoStringArgPassthrough extends StringColumnVTI

{

  private static final String[] COLUMN_NAMES = new String[] {"A", "B"};

  private final String _A;

  private final String _B;

  private boolean _hasMoreRows;

  private TwoStringArgPassthrough(String A, String B)

  {

    super(COLUMN_NAMES);

    _A = A;

    _B = B;

    _hasMoreRows = true;

  }

  /** Entry point bound to the table function */

  public static TwoStringArgPassthrough passthrough(String A, String B)

  {

    return new TwoStringArgPassthrough(A, B);

  }

  /** ResultSet overloads */

  public boolean next()

  {

    try

    {

      return _hasMoreRows;

    }

    finally

    {

      _hasMoreRows = false;

    }

  }

  public void close() { _hasMoreRows = false; }

  /** StringColumnVTI implementation */

  protected String getRawColumn(int columnNumber)

    throws SQLException

  {

    switch (columnNumber)

    {

    case 1: return _A;

    case 2: return _B;

    default: throw new SQLException("Unsupported column number: " + 
columnNumber);

    }

  }

}

Hope this helps,
-Rick



On Wed, Nov 14, 2018 at 7:59 PM Rick Hillegas <[email protected] <mailto:[email protected]>> wrote:

    Hi Alex,

    Thanks for compiling this list of issues. Some comments inline...

    On 11/14/18 1:22 PM, Alex O'Ree wrote:
    > Greetings. I'm looking for some kind of migration guide and for
    things
    > to watch out for when migration an application to derby.
    >
    > Since i haven't found one yet, i decide to write down and share
    some
    > of my notes on the things I've ran into so far:
    >
    > DDL - From postgres, there's lots of differences.
    > - Postgres 'text' becomes 'long varchar'
    Sounds like LONG VARCHAR wasn't long enough for you and you needed
    CLOB
    instead.
    > - Can't insert from 'text literal' into a blob without some
    quick code
    > and a function to convert it
    BLOB sounds like an odd analog for TEXT. Do you mean CLOB?
    > - Postgres gives you the option to select the index type, derby
    does
    > not appear to. have this function. Not really sure what kind of
    index
    > it is either. btree?
    All Derby indexes are btrees. They can be unique or non-unique.
    >
    > JDBC clients
    > - limit and offset has a bit of a strange syntax. most rdbs will
    > access just the literal limit 10 offset 1 syntax. Derby appears to
    > need to wrap this in { }, so select * from table { limit 10
    offset 10}
    Derby supports the SQL Standard OFFSET and FETCH clauses. See
    http://db.apache.org/derby/docs/10.14/ref/rrefsqljoffsetfetch.html
    > - from a JDBC client, don't include semicolons in your sql code.
    Again, Derby supports SQL Standard syntax. The semicolons are not
    part
    of the Standard grammar, although they are used by command line
    interpreters (like Derby own ij CLI) to mark the end of statements. I
    agree that rototilling your code to remove non-Standard semicolons
    sounds like a drag.
    >
    > For the last two, is this "normal"? I have a large code base and
    > refactoring it would be painful. I'm thinking it may be easier
    to hack
    > up the jdbc driver to "fix" the sql statements on the fly. Any
    > thoughts on this? maybe there is some kind of configuration
    setting to
    > make this easier?
    The place to hack this would be in the parsing layer, below the
    embedded
    JDBC layer. You might also want to take a look at the code for the ij
    tool, which has to deal with semicolons.

    Hope this helps,
    -Rick



Reply via email to