diff --git a/RELEASE.md b/RELEASE.md index 19e08ee..1b23204 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,3 +1,13 @@ +# Release 1.14 (2021-05-10) + +## EN + +- Fixed search under Entity without Key (table without Primary Key). + +## JA + +- Key の存在しないEntity (Primary Key のないテーブル) でも検索が正しく動作するよう変更。 + # Release 1.13 (2021-05-09) ## EN diff --git a/deploy2demosite.sh b/deploy2demosite.sh index 12718b8..7e3de5d 100644 --- a/deploy2demosite.sh +++ b/deploy2demosite.sh @@ -1,4 +1,4 @@ -OIYOKAN_VERSION=1.13.20210509a-SNAPSHOT +OIYOKAN_VERSION=1.14.20210510a-SNAPSHOT export OIYOKAN_VERSION mvn clean install diff --git a/pom.xml b/pom.xml index 4577ad7..d8816ac 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 jp.igapyon.oiyokan oiyokan - 1.13.20210509b-SNAPSHOT + 1.14.20210510a-SNAPSHOT oiyokan Oiyokan is a simple OData v4 Server. (based on Apache Olingo / Spring Boot / h2 database) diff --git a/src/main/java/jp/oiyokan/OiyokanConstants.java b/src/main/java/jp/oiyokan/OiyokanConstants.java index a36b37a..4f51a90 100755 --- a/src/main/java/jp/oiyokan/OiyokanConstants.java +++ b/src/main/java/jp/oiyokan/OiyokanConstants.java @@ -27,7 +27,7 @@ public class OiyokanConstants { /** * Oiyokan のバージョン番号 */ - public static final String VERSION = "1.13.20210509a"; + public static final String VERSION = "1.14.20210510a"; /** * 暗号化で利用するパスフレーズ。環境変数 OIYOKAN_PASSPHRASE で上書き動作。 diff --git a/src/main/java/jp/oiyokan/OiyokanMessages.java b/src/main/java/jp/oiyokan/OiyokanMessages.java index 0b744a4..d9a269a 100644 --- a/src/main/java/jp/oiyokan/OiyokanMessages.java +++ b/src/main/java/jp/oiyokan/OiyokanMessages.java @@ -85,7 +85,7 @@ public class OiyokanMessages { public static final String IY2105 = "[IY2105] UNEXPECTED: Fail to create ID EntitySet name"; public static final String IY2106 = "[IY2106] NOT SUPPORTED: unknown UUID object given"; public static final int IY2106_CODE = HttpStatusCode.BAD_REQUEST.getStatusCode(); - // IY2107 + public static final String IY2107 = "[IY2107] WARN: EntitySet should have Primary Key. First property was used for orderby."; public static final String IY2108 = "[IY2108] NOT SUPPORTED: Parameter Type"; public static final int IY2108_CODE = HttpStatusCode.BAD_REQUEST.getStatusCode(); diff --git a/src/main/java/jp/oiyokan/basic/sql/OiyoSqlQueryListBuilder.java b/src/main/java/jp/oiyokan/basic/sql/OiyoSqlQueryListBuilder.java index 08e2162..362b7fd 100755 --- a/src/main/java/jp/oiyokan/basic/sql/OiyoSqlQueryListBuilder.java +++ b/src/main/java/jp/oiyokan/basic/sql/OiyoSqlQueryListBuilder.java @@ -29,6 +29,7 @@ import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl; import jp.oiyokan.OiyokanConstants; +import jp.oiyokan.OiyokanMessages; import jp.oiyokan.common.OiyoCommonJdbcUtil; import jp.oiyokan.common.OiyoInfo; import jp.oiyokan.common.OiyoInfoUtil; @@ -367,17 +368,26 @@ private void expandOrderBy(UriInfo uriInfo) throws ODataApplicationException { private void expandOrderByWithPrimary() throws ODataApplicationException { final OiyoSettingsEntitySet entitySet = OiyoInfoUtil.getOiyoEntitySet(oiyoInfo, sqlInfo.getEntitySetName()); - // 無指定の場合はプライマリキーにてソート. - boolean isFirst = true; - for (String look : entitySet.getEntityType().getKeyName()) { - if (isFirst) { - isFirst = false; - } else { - sqlInfo.getSqlBuilder().append(","); - } - - final OiyoSettingsProperty prop = OiyoInfoUtil.getOiyoEntityProperty(oiyoInfo, entitySet.getName(), look); + if (entitySet.getEntityType().getKeyName().size() != 0) { + // 無指定の場合はプライマリキーにてソート. + boolean isFirst = true; + for (String look : entitySet.getEntityType().getKeyName()) { + if (isFirst) { + isFirst = false; + } else { + sqlInfo.getSqlBuilder().append(","); + } + final OiyoSettingsProperty prop = OiyoInfoUtil.getOiyoEntityProperty(oiyoInfo, entitySet.getName(), + look); + sqlInfo.getSqlBuilder().append(OiyoCommonJdbcUtil.escapeKakkoFieldName(sqlInfo, prop.getDbName())); + } + } else { + // プライマリキーの存在しない異常状態の場合です. しかたなく最初の項目でソートします。 + final OiyoSettingsProperty prop = entitySet.getEntityType().getProperty().get(0); + // [IY2107] WARN: EntitySet should have Primary Key. First property was used for + // orderby. + log.warn(OiyokanMessages.IY2107 + ": " + entitySet.getName() + ": " + prop.getName()); sqlInfo.getSqlBuilder().append(OiyoCommonJdbcUtil.escapeKakkoFieldName(sqlInfo, prop.getDbName())); } } diff --git a/src/test/java/jp/oiyokan/db/testdb/query/UnitTestNonKeyQuery01Test.java b/src/test/java/jp/oiyokan/db/testdb/query/UnitTestNonKeyQuery01Test.java new file mode 100644 index 0000000..6c04db7 --- /dev/null +++ b/src/test/java/jp/oiyokan/db/testdb/query/UnitTestNonKeyQuery01Test.java @@ -0,0 +1,42 @@ +/* + * Copyright 2021 Toshiki Iga + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package jp.oiyokan.db.testdb.query; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.apache.olingo.server.api.ODataResponse; +import org.junit.jupiter.api.Test; + +import jp.oiyokan.OiyokanUnittestUtil; +import jp.oiyokan.common.OiyoInfo; +import jp.oiyokan.util.OiyokanTestUtil; + +/** + * Primary Key のない誤ったテーブルであっても正常動作することの確認。 + */ +class UnitTestNonKeyQuery01Test { + @Test + void test01() throws Exception { + @SuppressWarnings("unused") + final OiyoInfo oiyoInfo = OiyokanUnittestUtil.setupUnittestDatabase(); + + final ODataResponse resp = OiyokanTestUtil.callGet("/ODataTest9", "$select=Name,Description"); + final String result = OiyokanTestUtil.stream2String(resp.getContent()); + + assertEquals("{\"@odata.context\":\"$metadata#ODataTest9\",\"value\":[]}", result); + assertEquals(200, resp.getStatusCode()); + } +} diff --git a/src/test/resources/oiyokan/oiyokan-unittest-settings.json b/src/test/resources/oiyokan/oiyokan-unittest-settings.json index 8dc38a9..17668ad 100644 --- a/src/test/resources/oiyokan/oiyokan-unittest-settings.json +++ b/src/test/resources/oiyokan/oiyokan-unittest-settings.json @@ -891,6 +891,46 @@ ] } }, + { + "name": "ODataTest9", + "description": "Description.", + "dbSettingName": "oiyoUnitTestDb", + "canCreate": true, + "canRead": true, + "canUpdate": true, + "canDelete": true, + "omitCountAll": false, + "jdbcStmtTimeout": 30, + "entityType": { + "name": "ODataTest9", + "dbName": "ODataTest9", + "keyName": [], + "property": [ + { + "name": "Name", + "dbName": "Name", + "edmType": "Edm.String", + "jdbcType": "Types.VARCHAR", + "dbType": "VARCHAR", + "nullable": true, + "maxLength": 80, + "dbDefault": "'Ubnormal test case. Without Primary Key.'", + "filterTreatNullAsBlank": true + }, + { + "name": "Description", + "dbName": "Description", + "edmType": "Edm.String", + "jdbcType": "Types.VARCHAR", + "dbType": "VARCHAR", + "nullable": true, + "maxLength": 250, + "dbDefault": "'Ubnormal test case. Without Primary Key.'", + "filterTreatNullAsBlank": true + } + ] + } + }, { "name": "ODataTestFulls1", "description": "Description.", diff --git a/src/test/resources/oiyokan/sql/oiyokan-unittest-db-h2.sql b/src/test/resources/oiyokan/sql/oiyokan-unittest-db-h2.sql index 0109825..1016973 100644 --- a/src/test/resources/oiyokan/sql/oiyokan-unittest-db-h2.sql +++ b/src/test/resources/oiyokan/sql/oiyokan-unittest-db-h2.sql @@ -123,6 +123,12 @@ CREATE TABLE IF NOT EXISTS , PRIMARY KEY(MainKey,SubKey,SubSubKey) ); +CREATE TABLE IF NOT EXISTS + ODataTest9 ( + Name VARCHAR(80) DEFAULT 'Ubnormal test case. Without Primary Key.' + , Description VARCHAR(250) DEFAULT 'Ubnormal test case. Without Primary Key.' + ); + CREATE TABLE IF NOT EXISTS ODataTestFulls1 ( ID IDENTITY NOT NULL