11
19
public class PgFunction {
14
* Pattern for checking whether function definition contains CREATE
15
* OR REPLACE FUNCTION string.
17
private static final Pattern PATTERN_CREATE_FUNCTION = Pattern.compile(
18
"(?:CREATE[\\s]+FUNCTION)([\\s]+.*)",
19
Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
21
* Declaration of the function. Contains function name and
24
private String declaration;
26
* Whole definition of the function.
28
private String definition;
30
22
* Name of the function including argument types.
32
24
private String name;
28
@SuppressWarnings("CollectionWithoutInitialCapacity")
29
private final List<Argument> arguments = new ArrayList<Argument>();
31
* Whole definition of the function from RETURNS keyword.
35
36
* Returns creation SQL of the function.
37
38
* @return creation SQL
39
40
public String getCreationSQL() {
41
final Matcher matcher = PATTERN_CREATE_FUNCTION.matcher(definition);
43
if (matcher.matches()) {
44
result = "CREATE OR REPLACE FUNCTION" + matcher.group(1);
46
result = getDefinition();
41
final StringBuilder sbSQL = new StringBuilder(500);
42
sbSQL.append("CREATE OR REPLACE FUNCTION ");
43
sbSQL.append(PgDiffUtils.getQuotedName(name));
46
boolean addComma = false;
48
for (final Argument argument : arguments) {
53
sbSQL.append(argument.getDeclaration(true));
53
* Setter for {@link #declaration}.
55
* @param declaration {@link #declaration}
57
public void setDeclaration(final String declaration) {
58
this.declaration = declaration;
62
* Getter for {@link #declaration}.
64
* @return {@link #declaration}
66
public String getDeclaration() {
71
* Setter for {@link #definition}.
73
* @param definition {@link #definition}
75
public void setDefinition(final String definition) {
76
this.definition = definition;
80
* Getter for {@link #definition}.
82
* @return {@link #definition}
84
public String getDefinition() {
61
return sbSQL.toString();
65
* Setter for {@link #body}.
67
* @param body {@link #body}
69
public void setBody(final String body) {
74
* Getter for {@link #body}.
76
* @return {@link #body}
78
public String getBody() {
118
* @param object {@inheritDoc}
120
* @return {@inheritDoc}
133
* Getter for {@link #arguments}. List cannot be modified.
135
* @return {@link #arguments}
137
public List<Argument> getArguments() {
138
return Collections.unmodifiableList(arguments);
142
* Adds argument to the list of arguments.
144
* @param argument argument
146
public void addArgument(final Argument argument) {
147
arguments.add(argument);
151
* Returns function signature. It consists of unquoted name and argument
154
* @return function signature
156
public String getSignature() {
157
final StringBuilder sbString = new StringBuilder(100);
158
sbString.append(name);
159
sbString.append('(');
161
boolean addComma = false;
163
for (final Argument argument : arguments) {
164
if ("OUT".equalsIgnoreCase(argument.getMode())) {
169
sbString.append(',');
172
sbString.append(argument.getDataType().toLowerCase(Locale.ENGLISH));
177
sbString.append(')');
179
return sbString.toString();
123
183
public boolean equals(final Object object) {
184
if (!(object instanceof PgFunction)) {
186
} else if (object == this) {
124
190
return equals(object, false);
128
194
* Compares two objects whether they are equal. If both objects are of the
129
* same class but they equal just in whitespace in {@link #definition},
195
* same class but they equal just in whitespace in {@link #body},
130
196
* they are considered being equal.
132
198
* @param object object to be compared
133
199
* @param ignoreFunctionWhitespace whether multiple whitespaces in function
134
* {@link #definition} should be ignored
200
* {@link #body} should be ignored
136
* @return {@inheritDoc}
202
* @return true if <code>object</code> is pg function and the function code
203
* is the same when compared ignoring whitespace, otherwise returns false
138
205
public boolean equals(final Object object,
139
206
final boolean ignoreFunctionWhitespace) {
144
211
} else if (object instanceof PgFunction) {
145
212
final PgFunction function = (PgFunction) object;
146
final String thisDefinition;
147
final String thatDefinition;
214
if (name == null && function.getName() != null
215
|| name != null && !name.equals(function.getName())) {
219
final String thisBody;
220
final String thatBody;
149
222
if (ignoreFunctionWhitespace) {
150
thisDefinition = getDefinition().replaceAll("\\s+", " ");
152
function.getDefinition().replaceAll("\\s+", " ");
154
thisDefinition = getDefinition();
155
thatDefinition = function.getDefinition();
157
equals = declaration.equals(function.declaration)
158
&& thisDefinition.equals(thatDefinition)
159
&& name.equals(function.name);
223
thisBody = body.replaceAll("\\s+", " ");
225
function.getBody().replaceAll("\\s+", " ");
228
thatBody = function.getBody();
231
if (thisBody == null && thatBody != null
232
|| thisBody != null && !thisBody.equals(thatBody)) {
236
if (arguments.size() != function.getArguments().size()) {
239
for (int i = 0; i < arguments.size(); i++) {
240
if (!arguments.get(i).equals(function.getArguments().get(i))) {
168
* @return {@inheritDoc}
171
253
public int hashCode() {
172
return (getClass().getName() + "|" + declaration + "|" + getDefinition()
173
+ "|" + name).hashCode();
254
final StringBuilder sbString = new StringBuilder(500);
255
sbString.append(body);
256
sbString.append('|');
257
sbString.append(name);
259
for (final Argument argument : arguments) {
260
sbString.append('|');
261
sbString.append(argument.getDeclaration(true));
264
return sbString.toString().hashCode();
268
* Function argument information.
270
@SuppressWarnings("PublicInnerClass")
271
public static class Argument {
276
private String mode = "IN";
282
* Argument data type.
284
private String dataType;
286
* Argument default expression.
288
private String defaultExpression;
291
* Getter for {@link #dataType}.
293
* @return {@link #dataType}
295
public String getDataType() {
300
* Setter for {@link #dataType}.
302
* @param dataType {@link #dataType}
304
public void setDataType(final String dataType) {
305
this.dataType = dataType;
309
* Getter for {@link #defaultExpression}.
311
* @return {@link #defaultExpression}
313
public String getDefaultExpression() {
314
return defaultExpression;
318
* Setter for {@link #defaultExpression}.
320
* @param defaultExpression {@link #defaultExpression}
322
public void setDefaultExpression(final String defaultExpression) {
323
this.defaultExpression = defaultExpression;
327
* Getter for {@link #mode}.
329
* @return {@link #mode}
331
public String getMode() {
336
* Setter for {@link #mode}.
338
* @param mode {@link #mode}
340
public void setMode(final String mode) {
341
this.mode = mode == null || mode.isEmpty() ? "IN" : mode;
345
* Getter for {@link #name}.
347
* @return {@link #name}
349
public String getName() {
354
* Setter for {@link #name}.
356
* @param name {@link #name}
358
public void setName(final String name) {
363
* Creates argument declaration.
365
* @param includeDefaultValue whether to include default value
367
* @return argument declaration
369
public String getDeclaration(final boolean includeDefaultValue) {
370
final StringBuilder sbString = new StringBuilder(50);
372
if (mode != null && !"IN".equalsIgnoreCase(mode)) {
373
sbString.append(mode);
374
sbString.append(' ');
377
if (name != null && !name.isEmpty()) {
378
sbString.append(PgDiffUtils.getQuotedName(name));
379
sbString.append(' ');
382
sbString.append(dataType);
384
if (includeDefaultValue && defaultExpression != null
385
&& !defaultExpression.isEmpty()) {
386
sbString.append(" = ");
387
sbString.append(defaultExpression);
390
return sbString.toString();
394
public boolean equals(final Object obj) {
395
if (!(obj instanceof Argument)) {
397
} else if (this == obj) {
401
final Argument argument = (Argument) obj;
403
return (dataType == null ? argument.getDataType() == null
404
: dataType.equalsIgnoreCase(argument.getDataType()))
405
&& (defaultExpression == null
406
? argument.getDefaultExpression() == null
407
: defaultExpression.equals(defaultExpression))
408
&& (mode == null ? argument.getMode() == null
409
: mode.equalsIgnoreCase(argument.getMode()))
410
&& (name == null ? argument.getName() == null
411
: name.equals(argument.getName()));
415
public int hashCode() {
416
final StringBuilder sbString = new StringBuilder(50);
418
mode == null ? null : mode.toUpperCase(Locale.ENGLISH));
419
sbString.append('|');
420
sbString.append(name);
421
sbString.append('|');
422
sbString.append(dataType == null ? null
423
: dataType.toUpperCase(Locale.ENGLISH));
424
sbString.append('|');
425
sbString.append(defaultExpression);
427
return sbString.toString().hashCode();