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