@@ -669,8 +669,8 @@ private String resolveReturningRowTable(ReturningClause returningClause, Source
669669 /**
670670 * Resolves one returned item, which is either a bare {@code *} or a direct
671671 * column of the write target, whose alias names its result component. A
672- * computed item has no schema type to generate, so it is rejected instead
673- * of analyzed.
672+ * computed item, a subscripted reference included, has no schema type to
673+ * generate, so it is rejected instead of analyzed.
674674 */
675675 private List <QueryColumn > resolveReturningItem (Expression expression , Alias alias , Source source ) {
676676 if (expression instanceof AllTableColumns ) {
@@ -695,8 +695,11 @@ private List<QueryColumn> resolveReturningItem(Expression expression, Alias alia
695695 return resolveAllColumns (source );
696696 }
697697
698- if (expression instanceof net .sf .jsqlparser .schema .Column column ) {
699- dev .sqlcj .schema .Column schemaColumn = resolveColumn (column , List .of (source )).column ();
698+ net .sf .jsqlparser .schema .Column returnedColumn = directColumn (expression );
699+
700+ if (returnedColumn != null ) {
701+ dev .sqlcj .schema .Column schemaColumn = resolveColumn (returnedColumn , List .of (source ))
702+ .column ();
700703
701704 return List .of (
702705 new QueryColumn (
@@ -808,6 +811,10 @@ private void requireNoCommonTableExpressions(List<?> withItems) {
808811 * list with the single values row, which is also their textual order. A
809812 * value that binds no placeholder reaches the database as written, so only
810813 * its target column must exist.
814+ *
815+ * <p>A target written with a subscript inserts into one element of its
816+ * array column, so its value is not typed from that column, which must
817+ * still exist.
811818 */
812819 private void resolveInsertParameters (
813820 Insert insert ,
@@ -829,13 +836,12 @@ private void resolveInsertParameters(
829836 }
830837
831838 for (int index = 0 ; index < columns .size (); index ++) {
832- String columnName = columns .get (index ).getUnquotedColumnName ();
839+ net .sf .jsqlparser .schema .Column target = columns .get (index );
840+ dev .sqlcj .schema .Column column = findColumn (table , target .getUnquotedColumnName ());
833841
834- resolveColumnValue (
835- values .get (index ),
836- findColumn (table , columnName ),
837- placeholders
838- );
842+ if (directColumn (target ) != null ) {
843+ resolveColumnValue (values .get (index ), column , placeholders );
844+ }
839845 }
840846 }
841847
@@ -857,6 +863,10 @@ private ParenthesedExpressionList<?> resolveInsertValues(Insert insert) {
857863 * parameter in the {@code WHERE} expression. An assigned value that binds
858864 * no placeholder reaches the database as written, so only its target
859865 * column must exist.
866+ *
867+ * <p>A target written with a subscript assigns one element of its array
868+ * column, so its value is not typed from that column, which must still
869+ * exist.
860870 */
861871 private void resolveUpdateSetParameters (
862872 List <UpdateSet > updateSets ,
@@ -870,13 +880,12 @@ private void resolveUpdateSetParameters(
870880 );
871881 }
872882
873- String columnName = updateSet .getColumn (0 ).getUnquotedColumnName ();
883+ net .sf .jsqlparser .schema .Column target = updateSet .getColumn (0 );
884+ dev .sqlcj .schema .Column column = findColumn (table , target .getUnquotedColumnName ());
874885
875- resolveColumnValue (
876- updateSet .getValue (0 ),
877- findColumn (table , columnName ),
878- placeholders
879- );
886+ if (directColumn (target ) != null ) {
887+ resolveColumnValue (updateSet .getValue (0 ), column , placeholders );
888+ }
880889 }
881890 }
882891
@@ -1724,7 +1733,9 @@ private void resolveParameters(
17241733 }
17251734
17261735 private void resolveInExpression (InExpression in , List <Source > sources , Placeholders placeholders ) {
1727- if (!(in .getLeftExpression () instanceof net .sf .jsqlparser .schema .Column column )) {
1736+ net .sf .jsqlparser .schema .Column column = directColumn (in .getLeftExpression ());
1737+
1738+ if (column == null ) {
17281739 return ;
17291740 }
17301741
@@ -1854,11 +1865,13 @@ private void resolveLikeExpression(
18541865 if (pattern != null ) {
18551866 requireSupportedLikePattern (like );
18561867
1857- if (!(left instanceof net .sf .jsqlparser .schema .Column column )) {
1868+ net .sf .jsqlparser .schema .Column testedColumn = directColumn (left );
1869+
1870+ if (testedColumn == null ) {
18581871 return ;
18591872 }
18601873
1861- dev .sqlcj .schema .Column schemaColumn = resolveColumn (column , sources ).column ();
1874+ dev .sqlcj .schema .Column schemaColumn = resolveColumn (testedColumn , sources ).column ();
18621875
18631876 requireSupportedType (schemaColumn );
18641877
@@ -1872,15 +1885,16 @@ private void resolveLikeExpression(
18721885 }
18731886
18741887 CastPlaceholder castPattern = placeholders .ofCast (right );
1888+ net .sf .jsqlparser .schema .Column testedColumn = directColumn (left );
18751889
18761890 if (
18771891 castPattern != null
18781892 && unsupportedLikePatternReason (like ) == null
1879- && left instanceof net . sf . jsqlparser . schema . Column column
1893+ && testedColumn != null
18801894 ) {
18811895 addCastParameter (
18821896 castPattern ,
1883- resolveColumn (column , sources ).column ().name (),
1897+ resolveColumn (testedColumn , sources ).column ().name (),
18841898 placeholders
18851899 );
18861900 }
@@ -1983,11 +1997,10 @@ private void resolveBetweenExpression(
19831997 return ;
19841998 }
19851999
1986- if (
1987- left instanceof net .sf .jsqlparser .schema .Column column
1988- && (bindsValue (start , placeholders ) || bindsValue (end , placeholders ))
1989- ) {
1990- dev .sqlcj .schema .Column schemaColumn = resolveColumn (column , sources ).column ();
2000+ net .sf .jsqlparser .schema .Column testedColumn = directColumn (left );
2001+
2002+ if (testedColumn != null && (bindsValue (start , placeholders ) || bindsValue (end , placeholders ))) {
2003+ dev .sqlcj .schema .Column schemaColumn = resolveColumn (testedColumn , sources ).column ();
19912004
19922005 resolveColumnValue (start , schemaColumn , placeholders );
19932006 resolveColumnValue (end , schemaColumn , placeholders );
@@ -2013,52 +2026,55 @@ private void resolveParameterComparison(
20132026 Placeholder leftPlaceholder = placeholders .of (left );
20142027 Placeholder rightPlaceholder = placeholders .of (right );
20152028
2016- if (left instanceof net .sf .jsqlparser .schema .Column column && rightPlaceholder != null ) {
2029+ net .sf .jsqlparser .schema .Column leftColumn = directColumn (left );
2030+ net .sf .jsqlparser .schema .Column rightColumn = directColumn (right );
2031+
2032+ if (leftColumn != null && rightPlaceholder != null ) {
20172033 addParameter (
20182034 rightPlaceholder ,
2019- resolveColumn (column , sources ).column (),
2035+ resolveColumn (leftColumn , sources ).column (),
20202036 placeholders
20212037 );
20222038 return ;
20232039 }
20242040
2025- if (leftPlaceholder != null && right instanceof net . sf . jsqlparser . schema . Column column ) {
2041+ if (leftPlaceholder != null && rightColumn != null ) {
20262042 addParameter (
20272043 leftPlaceholder ,
2028- resolveColumn (column , sources ).column (),
2044+ resolveColumn (rightColumn , sources ).column (),
20292045 placeholders
20302046 );
20312047 return ;
20322048 }
20332049
2034- if (comparison instanceof EqualsTo && left instanceof net . sf . jsqlparser . schema . Column column ) {
2050+ if (comparison instanceof EqualsTo && leftColumn != null ) {
20352051 Expression listArgument = anyListArgument (right , placeholders );
20362052
20372053 if (listArgument != null ) {
2038- resolveAnyListParameter (listArgument , column , sources , placeholders );
2054+ resolveAnyListParameter (listArgument , leftColumn , sources , placeholders );
20392055 return ;
20402056 }
20412057 }
20422058
20432059 if (isColumnTypedComparison (comparison )) {
2044- if (left instanceof net . sf . jsqlparser . schema . Column column ) {
2060+ if (leftColumn != null ) {
20452061 CastPlaceholder cast = placeholders .ofCast (right );
20462062
20472063 if (cast != null ) {
20482064 addCastParameter (
20492065 cast ,
2050- resolveColumn (column , sources ).column ().name (),
2066+ resolveColumn (leftColumn , sources ).column ().name (),
20512067 placeholders
20522068 );
20532069 return ;
20542070 }
2055- } else if (right instanceof net . sf . jsqlparser . schema . Column column ) {
2071+ } else if (rightColumn != null ) {
20562072 CastPlaceholder cast = placeholders .ofCast (left );
20572073
20582074 if (cast != null ) {
20592075 addCastParameter (
20602076 cast ,
2061- resolveColumn (column , sources ).column ().name (),
2077+ resolveColumn (rightColumn , sources ).column ().name (),
20622078 placeholders
20632079 );
20642080 }
@@ -2372,6 +2388,9 @@ private Placeholders toPlaceholders(ParsedSql parsedSql, Schema schema) {
23722388 * <p>A bare placeholder projection is a placeholder a cast makes a
23732389 * supported result column, so it is rejected as an untyped placeholder
23742390 * rather than as an unsupported result expression.
2391+ *
2392+ * <p>A subscripted reference projects an element rather than the column, so
2393+ * it is rejected as any other computed item is, and a cast states its type.
23752394 */
23762395 private List <QueryColumn > resolveColumns (
23772396 PlainSelect plainSelect ,
@@ -2405,8 +2424,10 @@ private List<QueryColumn> resolveColumns(
24052424 continue ;
24062425 }
24072426
2408- if (expression instanceof net .sf .jsqlparser .schema .Column column ) {
2409- ResolvedColumn resolved = resolveColumn (column , sources );
2427+ net .sf .jsqlparser .schema .Column selectedColumn = directColumn (expression );
2428+
2429+ if (selectedColumn != null ) {
2430+ ResolvedColumn resolved = resolveColumn (selectedColumn , sources );
24102431 dev .sqlcj .schema .Column schemaColumn = resolved .column ();
24112432
24122433 columns .add (
@@ -2551,6 +2572,22 @@ private String selectedColumnName(Alias alias, dev.sqlcj.schema.Column schemaCol
25512572 : alias .getUnquotedName ();
25522573 }
25532574
2575+ /**
2576+ * Reports the column one expression reads directly, and {@code null} when
2577+ * the expression reads none. A reference written with a subscript or a
2578+ * slice, such as {@code labels[1]} or {@code labels[1:2]}, reads one
2579+ * element or one range of the column's array value rather than the column,
2580+ * so it states neither the type nor the name of the column it reads, and
2581+ * every rule that takes a type or a name from a column leaves it to the
2582+ * rules of any other expression.
2583+ */
2584+ private net .sf .jsqlparser .schema .Column directColumn (Expression expression ) {
2585+ return expression instanceof net .sf .jsqlparser .schema .Column column
2586+ && column .getArrayConstructor () == null
2587+ ? column
2588+ : null ;
2589+ }
2590+
25542591 /**
25552592 * Resolves one column reference against the ordered query sources. A
25562593 * qualified reference resolves through the exposed source name, and an
0 commit comments