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+ private StringBuilder appendTo (StringBuilder builder ) {
69+ if (options .isEmpty () || options .contains (null )) {
70+ throw new IllegalStateException ("Invalid SQL Server SET option group" );
71+ }
72+ for (int i = 0 ; i < options .size (); i ++) {
73+ if (i > 0 ) {
74+ builder .append (", " );
75+ }
76+ builder .append (options .get (i ));
77+ }
78+ return builder .append (on ? " ON" : " OFF" );
79+ }
80+ }
81+
82+ public OnOffOptions getOnOffOptions () {
83+ return onOffOptions ;
84+ }
85+
86+ /** Selects SQL Server option syntax, clearing any existing assignments and scope. */
87+ public void setOnOffOptions (OnOffOptions onOffOptions ) {
88+ Objects .requireNonNull (onOffOptions , "onOffOptions" );
89+ clear ();
90+ this .onOffOptions = onOffOptions ;
91+ }
2692
2793 public SetStatement () {
2894 // empty constructor
@@ -33,6 +99,7 @@ public SetStatement(Object name, ExpressionList<?> value) {
3399 }
34100
35101 public void add (Object name , ExpressionList <?> value , boolean useEqual ) {
102+ onOffOptions = null ;
36103 values .add (new NameExpr (name , value , useEqual ));
37104 }
38105
@@ -103,35 +170,53 @@ public void setExpressions(int idx, ExpressionList<?> expressions) {
103170 values .get (idx ).expressions = expressions ;
104171 }
105172
106- private String toString (NameExpr ne ) {
107- return ne .name + (ne .useEqual ? " = " : " " )
108- + PlainSelect .getStringList (ne .expressions , true , false );
173+ /** Shares statement punctuation with deparsers while allowing expression visitors. */
174+ public StringBuilder appendTo (StringBuilder builder , Consumer <Expression > expressionRenderer ) {
175+ builder .append ("SET " );
176+ if (onOffOptions != null ) {
177+ if (!values .isEmpty () || effectParameter != null ) {
178+ throw new IllegalStateException (
179+ "SET options cannot be combined with assignments or scope" );
180+ }
181+ return onOffOptions .appendTo (builder );
182+ }
183+ if (effectParameter != null ) {
184+ builder .append (effectParameter ).append (" " );
185+ }
186+ for (int i = 0 ; i < values .size (); i ++) {
187+ if (i > 0 ) {
188+ builder .append (", " );
189+ }
190+ appendAssignment (builder , values .get (i ), expressionRenderer );
191+ }
192+ return builder ;
109193 }
110194
111- @ Override
112- public String toString () {
113- StringBuilder b = new StringBuilder ("SET " );
114- if (effectParameter != null ) {
115- b .append (effectParameter ).append (" " );
116- }
117- boolean addComma = false ;
118- for (NameExpr ne : values ) {
119- if (addComma ) {
120- b .append (", " );
121- } else {
122- addComma = true ;
195+ private static void appendAssignment (StringBuilder builder , NameExpr value ,
196+ Consumer <Expression > expressionRenderer ) {
197+ builder .append (value .name ).append (value .useEqual ? " = " : " " );
198+ if (value .expressions != null ) {
199+ for (int i = 0 ; i < value .expressions .size (); i ++) {
200+ if (i > 0 ) {
201+ builder .append (", " );
202+ }
203+ expressionRenderer .accept ((Expression ) value .expressions .get (i ));
123204 }
124- b .append (toString (ne ));
125205 }
206+ }
126207
127- return b .toString ();
208+ @ Override
209+ public String toString () {
210+ StringBuilder builder = new StringBuilder ();
211+ return appendTo (builder , builder ::append ).toString ();
128212 }
129213
130214 public List <NameExpr > getKeyValuePairs () {
131215 return values ;
132216 }
133217
134218 public void addKeyValuePairs (Collection <NameExpr > keyValuePairs ) {
219+ onOffOptions = null ;
135220 values .addAll (keyValuePairs );
136221 }
137222
@@ -140,6 +225,7 @@ public void addKeyValuePairs(NameExpr... keyValuePairs) {
140225 }
141226
142227 public void clear () {
228+ onOffOptions = null ;
143229 values .clear ();
144230 effectParameter = null ;
145231 }
0 commit comments