IGNITE-6111: SQL: ability to execute INSERT INTO without specifying column names. This closes #2881.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/4c8bc53e Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/4c8bc53e Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/4c8bc53e Branch: refs/heads/ignite-3478 Commit: 4c8bc53e6c597657ad6541a518fb0e4c031c7799 Parents: 4c31549 Author: devozerov <[email protected]> Authored: Thu Oct 26 16:03:58 2017 +0300 Committer: devozerov <[email protected]> Committed: Thu Oct 26 16:03:58 2017 +0300 ---------------------------------------------------------------------- .../processors/query/h2/IgniteH2Indexing.java | 27 ++++++++- .../processors/query/h2/opt/GridH2Table.java | 60 ++++++++++++++++++++ .../IgniteCacheInsertSqlQuerySelfTest.java | 18 ++++++ 3 files changed, 104 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/4c8bc53e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java index 9321c85..a861614 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java @@ -392,13 +392,38 @@ public class IgniteH2Indexing implements GridQueryIndexing { return stmt; } - stmt = c.prepareStatement(sql); + stmt = prepare0(c, sql); cache.put(sql, stmt); return stmt; } else + return prepare0(c, sql); + } + + /** + * Prepare statement. + * + * @param c Connection. + * @param sql SQL. + * @return Prepared statement. + * @throws SQLException If failed. + */ + private PreparedStatement prepare0(Connection c, String sql) throws SQLException { + boolean insertHack = GridH2Table.insertHackRequired(sql); + + if (insertHack) { + GridH2Table.insertHack(true); + + try { + return c.prepareStatement(sql); + } + finally { + GridH2Table.insertHack(false); + } + } + else return c.prepareStatement(sql); } http://git-wip-us.apache.org/repos/asf/ignite/blob/4c8bc53e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java index 6c353e9..ac70c54 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java @@ -36,6 +36,7 @@ import org.apache.ignite.internal.processors.query.h2.database.H2RowFactory; import org.apache.ignite.internal.processors.query.h2.database.H2TreeIndex; import org.apache.ignite.internal.util.typedef.F; import org.h2.command.ddl.CreateTableData; +import org.h2.command.dml.Insert; import org.h2.engine.DbObject; import org.h2.engine.Session; import org.h2.engine.SysProperties; @@ -63,6 +64,9 @@ import static org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueR * H2 Table implementation. */ public class GridH2Table extends TableBase { + /** Insert hack flag. */ + private static final ThreadLocal<Boolean> INSERT_HACK = new ThreadLocal<>(); + /** Cache context. */ private final GridCacheContext cctx; @@ -958,4 +962,60 @@ public class GridH2Table extends TableBase { unlock(true); } } + + /** {@inheritDoc} */ + @Override public Column[] getColumns() { + Boolean insertHack = INSERT_HACK.get(); + + if (insertHack != null && insertHack) { + StackTraceElement[] elems = Thread.currentThread().getStackTrace(); + + StackTraceElement elem = elems[2]; + + if (F.eq(elem.getClassName(), Insert.class.getName()) && F.eq(elem.getMethodName(), "prepare")) { + Column[] columns0 = new Column[columns.length - 3]; + + System.arraycopy(columns, 3, columns0, 0, columns0.length); + + return columns0; + } + } + + return columns; + } + + /** + * Set insert hack flag. + * + * @param val Value. + */ + public static void insertHack(boolean val) { + INSERT_HACK.set(val); + } + + /** + * Check whether insert hack is required. This is true in case statement contains "INSERT INTO ... VALUES". + * + * @param sql SQL statement. + * @return {@code True} if target combination is found. + */ + @SuppressWarnings("RedundantIfStatement") + public static boolean insertHackRequired(String sql) { + if (F.isEmpty(sql)) + return false; + + sql = sql.toLowerCase(); + + int idxInsert = sql.indexOf("insert"); + + if (idxInsert < 0) + return false; + + int idxInto = sql.indexOf("into", idxInsert); + + if (idxInto < 0) + return false; + + return true; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/4c8bc53e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInsertSqlQuerySelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInsertSqlQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInsertSqlQuerySelfTest.java index fbf01fa..0f72883 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInsertSqlQuerySelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInsertSqlQuerySelfTest.java @@ -119,6 +119,24 @@ public class IgniteCacheInsertSqlQuerySelfTest extends IgniteCacheAbstractInsert } /** + * Test insert with implicit column names. + */ + public void testImplicitColumnNames() { + IgniteCache<Key, Person> p = ignite(0).cache("K2P").withKeepBinary(); + + p.query(new SqlFieldsQuery( + "insert into Person values (1, 1, 'Vova')")).getAll(); + + assertEquals(createPerson(1, "Vova"), p.get(new Key(1))); + + p.query(new SqlFieldsQuery( + "insert into Person values (2, 2, 'Sergi'), (3, 3, 'Alex')")).getAll(); + + assertEquals(createPerson(2, "Sergi"), p.get(new Key(2))); + assertEquals(createPerson(3, "Alex"), p.get(new Key(3))); + } + + /** * */ public void testFieldsCaseSensitivity() {
