Skip to content

Commit c728dfd

Browse files
Merge branch 'develop' into fb_sql_experiment
2 parents a7ce75f + 2295f28 commit c728dfd

38 files changed

Lines changed: 497 additions & 426 deletions

announcements/src/org/labkey/announcements/model/AnnouncementType.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package org.labkey.announcements.model;
1717

1818
import org.jetbrains.annotations.NotNull;
19-
import org.jetbrains.annotations.Nullable;
2019
import org.labkey.api.announcements.CommSchema;
2120
import org.labkey.api.attachments.AttachmentParentType;
2221
import org.labkey.api.data.SQLFragment;
@@ -41,8 +40,8 @@ public static AttachmentParentType get()
4140
}
4241

4342
@Override
44-
public @Nullable SQLFragment getSelectParentEntityIdsSql()
43+
public @NotNull SQLFragment getSelectEntityIdAndDescriptionSql()
4544
{
46-
return new SQLFragment("SELECT EntityId FROM ").append(CommSchema.getInstance().getTableInfoAnnouncements(), "ann");
45+
return new SQLFragment("SELECT EntityId, Title AS Description FROM ").append(CommSchema.getInstance().getTableInfoAnnouncements(), "ann");
4746
}
4847
}

api/src/org/labkey/api/ApiModule.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@
106106
import org.labkey.api.module.ModuleLoader;
107107
import org.labkey.api.module.ModuleLoader.StartupPropertyStartupListener;
108108
import org.labkey.api.module.ModuleXml;
109-
import org.labkey.api.module.TomcatVersion;
110109
import org.labkey.api.query.AbstractQueryUpdateService;
111110
import org.labkey.api.query.AliasManager;
112111
import org.labkey.api.query.DetailsURL;
@@ -522,7 +521,6 @@ public void registerServlets(ServletContext servletCtx)
522521
Table.TestCase.class,
523522
TableSelectorTestCase.class,
524523
TempTableInClauseGenerator.TestCase.class,
525-
TomcatVersion.TestCase.class,
526524
URLHelper.TestCase.class,
527525
UserManager.TestCase.class,
528526
ViewCategoryManager.TestCase.class,

api/src/org/labkey/api/attachments/AttachmentParentType.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
package org.labkey.api.attachments;
1717

1818
import org.jetbrains.annotations.NotNull;
19-
import org.jetbrains.annotations.Nullable;
19+
import org.labkey.api.data.CoreSchema;
2020
import org.labkey.api.data.SQLFragment;
2121

2222
/**
@@ -25,7 +25,9 @@
2525
*/
2626
public interface AttachmentParentType
2727
{
28-
SQLFragment NO_ENTITY_IDS = new SQLFragment("SELECT NULL AS EntityId WHERE 1 = 0");
28+
SQLFragment NO_ROWS = new SQLFragment("SELECT NULL AS EntityId, NULL AS Description WHERE 1 = 0");
29+
SQLFragment PARENT_CONTAINER_SQL = new SQLFragment("SELECT EntityId, COALESCE(Name, '<Root>') AS Description FROM ")
30+
.append(CoreSchema.getInstance().getTableInfoContainers());
2931

3032
AttachmentParentType UNKNOWN = new AttachmentParentType()
3133
{
@@ -37,9 +39,9 @@ public String getUniqueName()
3739
}
3840

3941
@Override
40-
public void addWhereSql(SQLFragment sql, String parentColumn, String documentNameColumn)
42+
public @NotNull SQLFragment getSelectEntityIdAndDescriptionSql()
4143
{
42-
sql.append("0 = 1");
44+
return NO_ROWS;
4345
}
4446
};
4547

@@ -56,20 +58,27 @@ public void addWhereSql(SQLFragment sql, String parentColumn, String documentNam
5658
default void addWhereSql(SQLFragment sql, String parentColumn, String documentNameColumn)
5759
{
5860
SQLFragment selectSql = getSelectParentEntityIdsSql();
59-
if (selectSql == null)
60-
throw new IllegalStateException("Must override either addWhereSql() or getSelectParentEntityIdsSql()");
6161
sql.append(parentColumn).append(" IN (").append(selectSql).append(")");
6262
}
6363

6464
/**
65-
* Return a SQLFragment that selects all the EntityIds that might be attachment parents from the table(s) that
66-
* provide attachments of this type, without involving the core.Documents table. For example,
67-
* {@code SELECT EntityId FROM comm.Announcements}. Return null if this is not-yet-implemented or inappropriate.
68-
* For example, some attachments' parents are container IDs. If the method determines that no parents exist, then
69-
* return a valid query that selects no rows, for example, {@code NO_ENTITY_IDS}.
65+
* Return a SQLFragment that selects just the EntityId of rows that might be attachment parents from the table(s)
66+
* that provide attachments of this type, without involving the core.Documents table.
7067
*/
71-
default @Nullable SQLFragment getSelectParentEntityIdsSql()
68+
default @NotNull SQLFragment getSelectParentEntityIdsSql()
7269
{
73-
return null;
70+
SQLFragment selectSql = getSelectEntityIdAndDescriptionSql();
71+
72+
// The returned SQL is always used inside a subselect, so the alias doesn't have to be unique
73+
return new SQLFragment("SELECT EntityId FROM (").append(selectSql).append(") x");
7474
}
75+
76+
/**
77+
* Return a SQLFragment that selects the EntityId and an appropriate Description of all rows that might be
78+
* attachment parents from the table(s) that provide attachment parents of this type, without involving the
79+
* core.Documents table. For example, {@code SELECT EntityId, Title AS Description FROM comm.Announcements}.
80+
* If the method determines that no parents exist, then return a valid query that selects no rows, for example,
81+
* {@code NO_ROWS}.
82+
*/
83+
@NotNull SQLFragment getSelectEntityIdAndDescriptionSql();
7584
}

api/src/org/labkey/api/attachments/LookAndFeelResourceType.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,10 @@ public void addWhereSql(SQLFragment sql, String parentColumn, String documentNam
4949
sql.append(documentNameColumn).append(" LIKE '" + AttachmentCache.LOGO_FILE_NAME_PREFIX + "%' OR ");
5050
sql.append(documentNameColumn).append(" LIKE '" + AttachmentCache.MOBILE_LOGO_FILE_NAME_PREFIX + "%')");
5151
}
52+
53+
@Override
54+
public @NotNull SQLFragment getSelectEntityIdAndDescriptionSql()
55+
{
56+
return PARENT_CONTAINER_SQL;
57+
}
5258
}

api/src/org/labkey/api/collections/LabKeyCollectors.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.json.JSONArray;
77
import org.junit.Assert;
88
import org.junit.Test;
9+
import org.labkey.api.data.SQLFragment;
910
import org.labkey.api.util.HtmlString;
1011
import org.labkey.api.util.HtmlStringBuilder;
1112

@@ -14,6 +15,7 @@
1415
import java.util.Comparator;
1516
import java.util.HashMap;
1617
import java.util.LinkedHashMap;
18+
import java.util.LinkedList;
1719
import java.util.List;
1820
import java.util.Map;
1921
import java.util.Objects;
@@ -222,6 +224,18 @@ public static Collector<HtmlString, HtmlStringBuilder, HtmlString> joining(HtmlS
222224
);
223225
}
224226

227+
/**
228+
* Returns a {@link Collector} that joins {@link SQLFragment}s into a single {@link SQLFragment} separated by delimiter
229+
*/
230+
public static Collector<SQLFragment, List<SQLFragment>, SQLFragment> joining(SQLFragment delimiter) {
231+
return Collector.of(
232+
LinkedList::new,
233+
List::add,
234+
(list1, list2) -> {list1.addAll(list2); return list1;},
235+
(list) -> SQLFragment.join(list, delimiter)
236+
);
237+
}
238+
225239
public static class TestCase extends Assert
226240
{
227241
@Test

api/src/org/labkey/api/data/ConvertHelper.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.junit.Assert;
4747
import org.junit.Test;
4848
import org.labkey.api.collections.ConcurrentHashSet;
49+
import org.labkey.api.exp.PropertyType;
4950
import org.labkey.api.gwt.client.DefaultScaleType;
5051
import org.labkey.api.gwt.client.FacetingBehaviorType;
5152
import org.labkey.api.query.FieldKey;
@@ -1210,6 +1211,61 @@ public void testInvalidInfDoubleConverter()
12101211
}
12111212
}
12121213
}
1214+
1215+
@Test
1216+
public void testEmpty()
1217+
{
1218+
assertNull(JdbcType.CHAR.convert(""));
1219+
assertNull(JdbcType.VARCHAR.convert(""));
1220+
assertNull(JdbcType.LONGVARCHAR.convert(""));
1221+
1222+
// PropertyType is used for domain defined tables.
1223+
// I would expect these to return null.
1224+
assertEquals("", PropertyType.STRING.convert(""));
1225+
assertEquals("", PropertyType.MULTI_LINE.convert(""));
1226+
assertEquals("", PropertyType.XML_TEXT.convert(""));
1227+
1228+
// Since we often convert "through" string, I'm not sure this low-level
1229+
// method should modify "". This could potentially mess up
1230+
// converting array->string->array for instance.
1231+
// [] -> "" -> null
1232+
// vs
1233+
// [] -> "" -> []
1234+
assertNull(ConvertHelper.convert("", String.class));
1235+
assertNull(ConvertUtils.convert(""));
1236+
assertNull(ConvertUtils.convert("", String.class));
1237+
}
1238+
1239+
@Test
1240+
public void testBlank()
1241+
{
1242+
// blank strings do not get the empty string special handling.
1243+
assertEquals(" ", JdbcType.CHAR.convert(" "));
1244+
assertEquals(" ", JdbcType.VARCHAR.convert(" "));
1245+
assertEquals(" ", JdbcType.LONGVARCHAR.convert(" "));
1246+
assertEquals(" ", PropertyType.STRING.convert(" "));
1247+
assertEquals(" ", PropertyType.MULTI_LINE.convert(" "));
1248+
assertEquals(" ", PropertyType.XML_TEXT.convert(" "));
1249+
assertEquals(" ", ConvertHelper.convert(" ", String.class));
1250+
assertEquals(" ", ConvertUtils.convert(" "));
1251+
assertEquals(" ", ConvertUtils.convert(" ", String.class));
1252+
}
1253+
1254+
@Test
1255+
public void testTrim()
1256+
{
1257+
// convert() does not trim. That is handled in DataIterator.
1258+
// e.g. see SimpleTranslator.createConvertColumn()
1259+
assertEquals(" x ", JdbcType.CHAR.convert(" x "));
1260+
assertEquals(" x ", JdbcType.VARCHAR.convert(" x "));
1261+
assertEquals(" x ", JdbcType.LONGVARCHAR.convert(" x "));
1262+
assertEquals(" x ", PropertyType.STRING.convert(" x "));
1263+
assertEquals(" x ", PropertyType.MULTI_LINE.convert(" x "));
1264+
assertEquals(" x ", PropertyType.XML_TEXT.convert(" x "));
1265+
assertEquals(" x ", ConvertHelper.convert(" x ", String.class));
1266+
assertEquals(" x ", ConvertUtils.convert(" x "));
1267+
assertEquals(" x ", ConvertUtils.convert(" x ", String.class));
1268+
}
12131269
}
12141270

12151271
// Note: Keep in sync with LabKeySiteWrapper.getConversionErrorMessage()

api/src/org/labkey/api/data/JdbcType.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ protected void addSqlTypes(Collection<Integer> sqlTypes)
8989
{
9090
sqlTypes.add(Types.NCHAR);
9191
}
92+
93+
@Override
94+
public Object convert(Object o) throws ConversionException
95+
{
96+
return VARCHAR.convert(o);
97+
}
9298
},
9399

94100
DECIMAL(Types.DECIMAL, BigDecimal.class, null, "numberfield")

api/src/org/labkey/api/data/SQLFragment.java

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import java.util.TreeSet;
4848
import java.util.regex.Pattern;
4949
import java.util.stream.Collectors;
50-
import java.util.stream.StreamSupport;
5150

5251
import static org.labkey.api.query.ExprColumn.STR_TABLE_ALIAS;
5352

@@ -1339,25 +1338,23 @@ public int hashCode()
13391338
* concatenation using the provided separator. The parameters are combined to form the new parameter list.
13401339
*
13411340
* @param fragments SQLFragments to join together
1342-
* @param separator Separator to use on the SQL portion
1341+
* @param separator Separator to use
13431342
* @return A new SQLFragment that joins all the SQLFragments
13441343
*/
1345-
public static SQLFragment join(Iterable<SQLFragment> fragments, String separator)
1344+
public static SQLFragment join(Iterable<SQLFragment> fragments, SQLFragment separator)
13461345
{
1347-
if (separator.contains("?"))
1348-
throw new IllegalStateException("separator must not include a parameter marker");
1346+
SQLFragment join = new SQLFragment();
1347+
boolean first = true;
13491348

1350-
// Join all the SQL statements
1351-
String sql = StreamSupport.stream(fragments.spliterator(), false)
1352-
.map(SQLFragment::getSQL)
1353-
.collect(Collectors.joining(separator));
1354-
1355-
// Collect all the parameters to a single list
1356-
List<?> params = StreamSupport.stream(fragments.spliterator(), false)
1357-
.map(SQLFragment::getParams)
1358-
.flatMap(Collection::stream)
1359-
.collect(Collectors.toList());
1349+
for (SQLFragment fragment : fragments)
1350+
{
1351+
if (first)
1352+
first = false;
1353+
else
1354+
join.append(separator);
1355+
join.append(fragment);
1356+
}
13601357

1361-
return new SQLFragment(sql, params);
1358+
return join;
13621359
}
13631360
}

0 commit comments

Comments
 (0)