1111
1212import net .sf .jsqlparser .expression .Expression ;
1313import net .sf .jsqlparser .expression .operators .relational .ExpressionList ;
14- import net .sf .jsqlparser .statement .select .PlainSelect ;
1514
1615import java .io .Serializable ;
1716import java .util .ArrayList ;
1817import java .util .Arrays ;
1918import java .util .Collection ;
2019import java .util .List ;
20+ import java .util .Objects ;
21+ import java .util .function .Consumer ;
2122
2223public final class SetStatement implements Statement {
2324
2425 private final List <NameExpr > values = new ArrayList <>();
2526 private String effectParameter ;
27+ private OnOffOptions onOffOptions ;
28+
29+ /** SQL Server options that share the SET option [, option] ON | OFF syntax. */
30+ public enum OnOffOption {
31+ QUOTED_IDENTIFIER , CONCAT_NULL_YIELDS_NULL , CURSOR_CLOSE_ON_COMMIT , ARITHABORT , ARITHIGNORE , FMTONLY , NOCOUNT , NOEXEC , NUMERIC_ROUNDABORT , PARSEONLY , ANSI_DEFAULTS , ANSI_NULL_DFLT_OFF , ANSI_NULL_DFLT_ON , ANSI_NULLS , ANSI_PADDING , ANSI_WARNINGS , FORCEPLAN , SHOWPLAN_ALL , SHOWPLAN_TEXT , SHOWPLAN_XML , IMPLICIT_TRANSACTIONS , REMOTE_PROC_TRANSACTIONS , XACT_ABORT ;
32+
33+ public static OnOffOption fromName (String name ) {
34+ for (OnOffOption option : values ()) {
35+ if (option .name ().equalsIgnoreCase (name )) {
36+ return option ;
37+ }
38+ }
39+ return null ;
40+ }
41+ }
42+
43+ /** A group of options sharing one ON/OFF value; separate from assignment expressions. */
44+ public static final class OnOffOptions implements Serializable {
45+ private final List <OnOffOption > options ;
46+ private boolean on ;
47+
48+ public OnOffOptions (Collection <OnOffOption > options , boolean on ) {
49+ this .options = new ArrayList <>(options );
50+ if (this .options .isEmpty () || this .options .contains (null )) {
51+ throw new IllegalArgumentException ("At least one non-null SET option is required" );
52+ }
53+ this .on = on ;
54+ }
55+
56+ public List <OnOffOption > getOptions () {
57+ return options ;
58+ }
59+
60+ public boolean isOn () {
61+ return on ;
62+ }
63+
64+ public void setOn (boolean on ) {
65+ this .on = on ;
66+ }
67+ }
68+
69+ public OnOffOptions getOnOffOptions () {
70+ return onOffOptions ;
71+ }
72+
73+ /** Selects SQL Server option syntax, clearing any existing assignments and scope. */
74+ public void setOnOffOptions (OnOffOptions onOffOptions ) {
75+ Objects .requireNonNull (onOffOptions , "onOffOptions" );
76+ clear ();
77+ this .onOffOptions = onOffOptions ;
78+ }
2679
2780 public SetStatement () {
2881 // empty constructor
@@ -33,6 +86,7 @@ public SetStatement(Object name, ExpressionList<?> value) {
3386 }
3487
3588 public void add (Object name , ExpressionList <?> value , boolean useEqual ) {
89+ onOffOptions = null ;
3690 values .add (new NameExpr (name , value , useEqual ));
3791 }
3892
@@ -103,35 +157,55 @@ public void setExpressions(int idx, ExpressionList<?> expressions) {
103157 values .get (idx ).expressions = expressions ;
104158 }
105159
106- private String toString (NameExpr ne ) {
107- return ne .name + (ne .useEqual ? " = " : " " )
108- + PlainSelect .getStringList (ne .expressions , true , false );
109- }
110-
111- @ Override
112- public String toString () {
113- StringBuilder b = new StringBuilder ("SET " );
160+ /** Shares statement punctuation with deparsers while allowing expression visitors. */
161+ public StringBuilder appendTo (StringBuilder builder , Consumer <Expression > expressionRenderer ) {
162+ builder .append ("SET " );
163+ if (onOffOptions != null ) {
164+ if (!values .isEmpty () || effectParameter != null || onOffOptions .options .isEmpty ()
165+ || onOffOptions .options .contains (null )) {
166+ throw new IllegalStateException ("Invalid SQL Server SET option group" );
167+ }
168+ for (int i = 0 ; i < onOffOptions .options .size (); i ++) {
169+ if (i > 0 ) {
170+ builder .append (", " );
171+ }
172+ builder .append (onOffOptions .options .get (i ));
173+ }
174+ return builder .append (onOffOptions .on ? " ON" : " OFF" );
175+ }
114176 if (effectParameter != null ) {
115- b .append (effectParameter ).append (" " );
177+ builder .append (effectParameter ).append (" " );
116178 }
117- boolean addComma = false ;
118- for (NameExpr ne : values ) {
119- if (addComma ) {
120- b .append (", " );
121- } else {
122- addComma = true ;
179+ for (int i = 0 ; i < values .size (); i ++) {
180+ if (i > 0 ) {
181+ builder .append (", " );
182+ }
183+ NameExpr value = values .get (i );
184+ builder .append (value .name ).append (value .useEqual ? " = " : " " );
185+ if (value .expressions != null ) {
186+ for (int j = 0 ; j < value .expressions .size (); j ++) {
187+ if (j > 0 ) {
188+ builder .append (", " );
189+ }
190+ expressionRenderer .accept ((Expression ) value .expressions .get (j ));
191+ }
123192 }
124- b .append (toString (ne ));
125193 }
194+ return builder ;
195+ }
126196
127- return b .toString ();
197+ @ Override
198+ public String toString () {
199+ StringBuilder builder = new StringBuilder ();
200+ return appendTo (builder , builder ::append ).toString ();
128201 }
129202
130203 public List <NameExpr > getKeyValuePairs () {
131204 return values ;
132205 }
133206
134207 public void addKeyValuePairs (Collection <NameExpr > keyValuePairs ) {
208+ onOffOptions = null ;
135209 values .addAll (keyValuePairs );
136210 }
137211
@@ -140,6 +214,7 @@ public void addKeyValuePairs(NameExpr... keyValuePairs) {
140214 }
141215
142216 public void clear () {
217+ onOffOptions = null ;
143218 values .clear ();
144219 effectParameter = null ;
145220 }
0 commit comments