MariaDbErrorHandler.diff
build.gradle 2023-02-08 15:41:34 +0000 | ||
---|---|---|
848 | 848 | |
849 | 849 |
task mergeMariaDBUDFs(dependsOn: 'makeManifests') { |
850 | 850 |
inputs.files('udf/mariadb/udfs.sql', |
851 |
'udf/mariadb/guarded.sql', |
|
851 | 852 |
'udf/mariadb/error_handler.sql', |
852 | 853 |
"${buildDir}/udf/mariadb/getFWDVersion.sql") |
853 | 854 |
outputs.file( "${buildDir}/udf/mariadb/udfs.sql" ) |
src/com/goldencode/p2j/persist/FQLPreprocessor.java 2023-02-12 14:08:04 +0000 | ||
---|---|---|
3319 | 3319 |
int idxPos = next.getIndexPos(); |
3320 | 3320 |
parent = (HQLAst) next.getParent(); |
3321 | 3321 |
|
3322 |
String checkErrorFn = "checkError"; |
|
3323 |
String initErrorFn = "initError"; |
|
3324 |
if (dialect instanceof P2JSQLServer2008Dialect) |
|
3325 |
{ |
|
3326 |
checkErrorFn = "dbo.checkError_bb"; |
|
3327 |
initErrorFn = "dbo.initError_b"; |
|
3328 |
} |
|
3329 |
if (useSQLUdfs) |
|
3330 |
{ |
|
3331 |
checkErrorFn = udfSchema + checkErrorFn; |
|
3332 |
initErrorFn = udfSchema + initErrorFn; |
|
3333 |
} |
|
3322 |
String checkErrorFn = (useSQLUdfs ? udfSchema : "") + dialect.checkErrorFn(); |
|
3323 |
String initErrorFn = (useSQLUdfs ? udfSchema : "") + dialect.initErrorFn(); |
|
3334 | 3324 |
|
3335 | 3325 |
HQLAst checkErrFunc = createAstNode(FUNCTION, checkErrorFn, null); |
3336 | 3326 |
HQLAst initErrFunc = createAstNode(FUNCTION, initErrorFn, checkErrFunc); |
... | ... | |
3365 | 3355 |
// as operand of the logical operators: |
3366 | 3356 |
needSQLBooleanConversion.add(checkErrFunc); |
3367 | 3357 |
} |
3368 |
if (dialect instanceof P2JPostgreSQLDialect)
|
|
3358 |
if (useSQLUdfs)
|
|
3369 | 3359 |
{ |
3370 | 3360 |
Iterator<Aast> it = next.iterator(); |
3371 | 3361 |
while (it.hasNext()) |
... | ... | |
6361 | 6351 |
{ |
6362 | 6352 |
fn = fn.substring(udfSchema.length()); |
6363 | 6353 |
} |
6354 |
int pos = fn.lastIndexOf("_"); |
|
6355 |
if (pos > 0) |
|
6356 |
{ |
|
6357 |
fn = fn.substring(0, pos); |
|
6358 |
} |
|
6359 |
|
|
6364 | 6360 |
return UdfNamesHolder.UDF_NAMES.contains(fn); |
6365 | 6361 |
} |
6366 | 6362 |
|
src/com/goldencode/p2j/persist/dialect/Dialect.java 2023-02-12 15:00:42 +0000 | ||
---|---|---|
95 | 95 |
** SVL 20230110 P2JIndex.components() provides direct access to the components array in order to |
96 | 96 |
** improve performance. |
97 | 97 |
** ECF 20230127 Added resolveBooleanConstant method. |
98 |
** IAS 20230208 Dialect-specific error handler support. |
|
98 | 99 |
*/ |
99 | 100 | |
100 | 101 |
/* |
... | ... | |
168 | 169 |
import com.goldencode.p2j.persist.sequence.SequenceHandler; |
169 | 170 |
import com.goldencode.p2j.util.*; |
170 | 171 |
import com.goldencode.p2j.util.ErrorManager.*; |
172 |
import com.mchange.v2.c3p0.*; |
|
171 | 173 | |
172 | 174 |
/** |
173 | 175 |
* Extends the API defined by Hibernate's abstract <code>Dialect</code> class |
... | ... | |
403 | 405 |
*/ |
404 | 406 |
public abstract boolean useWordTables(); |
405 | 407 |
|
408 |
|
|
406 | 409 |
/** |
407 | 410 |
* Check if native UDFs are supported for the dialect |
408 | 411 |
* |
... | ... | |
420 | 423 |
return ""; |
421 | 424 |
} |
422 | 425 |
|
426 |
/** |
|
427 |
* Get name of the checkError UDF. |
|
428 |
* @return the name of the checkError UDF. |
|
429 |
*/ |
|
430 |
public String checkErrorFn() |
|
431 |
{ |
|
432 |
return "checkError"; |
|
433 |
} |
|
434 | ||
435 |
/** |
|
436 |
* Get name of the initError UDF. |
|
437 |
* @return the name of the initError UDF. |
|
438 |
*/ |
|
439 |
public String initErrorFn() |
|
440 |
{ |
|
441 |
return "initError"; |
|
442 |
} |
|
443 | ||
423 | 444 |
/** |
424 | 445 |
* Check if the exception was caused by an error in UDF. |
425 | 446 |
* @param e |
... | ... | |
493 | 514 |
} |
494 | 515 | |
495 | 516 |
/** |
517 |
* Get c3p0 ConnectionCustomizer class for the dialect. |
|
518 |
* |
|
519 |
* @param cfg |
|
520 |
* Database configuration. |
|
521 |
* @return c3p0 ConnectionCustomizer class for the dialect. |
|
522 |
*/ |
|
523 |
public Class<? extends AbstractConnectionCustomizer> connectionCustomizer(DatabaseConfig cfg) |
|
524 |
{ |
|
525 |
return null; |
|
526 |
} |
|
527 |
|
|
528 |
/** |
|
529 |
* Activate error handler at the database side. |
|
530 |
* @param conn |
|
531 |
* Database connection |
|
532 |
* @throws SQLException |
|
533 |
* on error. |
|
534 |
*/ |
|
535 |
public void activateErrorHandler(Connection conn) |
|
536 |
throws SQLException |
|
537 |
{ |
|
538 |
|
|
539 |
} |
|
540 |
|
|
541 |
/** |
|
542 |
* Reset error handler at the database side. |
|
543 |
* @param conn |
|
544 |
* Database connection |
|
545 |
* @throws SQLException |
|
546 |
* on error. |
|
547 |
*/ |
|
548 |
public void resetErrorHandler(Connection conn) |
|
549 |
throws SQLException |
|
550 |
{ |
|
551 |
|
|
552 |
} |
|
553 | ||
554 |
/** |
|
496 | 555 |
* Worker method for {@code generateTriggerDDLs()}. It generates the DDLs needed to create all |
497 | 556 |
* triggers in a database with a specific schema and using a certain dialect. |
498 | 557 |
* |
src/com/goldencode/p2j/persist/dialect/FWDMariaDBConnectionCustomizer.java 2023-02-12 14:57:59 +0000 | ||
---|---|---|
1 |
/* |
|
2 |
** Module : FWDMariaDBConnectionCustomizer |
|
3 |
** Abstract : c3p0 connection customizer |
|
4 |
** |
|
5 |
** Copyright (c) 2023, Golden Code Development Corporation. |
|
6 |
** |
|
7 |
** -#- -I- --Date-- ---------------------------------------Description--------------------------------------- |
|
8 |
** 001 IAS 20230208 Created initial version. |
|
9 |
*/ |
|
10 | ||
11 |
/* |
|
12 |
** This program is free software: you can redistribute it and/or modify |
|
13 |
** it under the terms of the GNU Affero General Public License as |
|
14 |
** published by the Free Software Foundation, either version 3 of the |
|
15 |
** License, or (at your option) any later version. |
|
16 |
** |
|
17 |
** This program is distributed in the hope that it will be useful, |
|
18 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
19 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
20 |
** GNU Affero General Public License for more details. |
|
21 |
** |
|
22 |
** You may find a copy of the GNU Affero GPL version 3 at the following |
|
23 |
** location: https://www.gnu.org/licenses/agpl-3.0.en.html |
|
24 |
** |
|
25 |
** Additional terms under GNU Affero GPL version 3 section 7: |
|
26 |
** |
|
27 |
** Under Section 7 of the GNU Affero GPL version 3, the following additional |
|
28 |
** terms apply to the works covered under the License. These additional terms |
|
29 |
** are non-permissive additional terms allowed under Section 7 of the GNU |
|
30 |
** Affero GPL version 3 and may not be removed by you. |
|
31 |
** |
|
32 |
** 0. Attribution Requirement. |
|
33 |
** |
|
34 |
** You must preserve all legal notices or author attributions in the covered |
|
35 |
** work or Appropriate Legal Notices displayed by works containing the covered |
|
36 |
** work. You may not remove from the covered work any author or developer |
|
37 |
** credit already included within the covered work. |
|
38 |
** |
|
39 |
** 1. No License To Use Trademarks. |
|
40 |
** |
|
41 |
** This license does not grant any license or rights to use the trademarks |
|
42 |
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks |
|
43 |
** of Golden Code Development Corporation. You are not authorized to use the |
|
44 |
** name Golden Code, FWD, or the names of any author or contributor, for |
|
45 |
** publicity purposes without written authorization. |
|
46 |
** |
|
47 |
** 2. No Misrepresentation of Affiliation. |
|
48 |
** |
|
49 |
** You may not represent yourself as Golden Code Development Corporation or FWD. |
|
50 |
** |
|
51 |
** You may not represent yourself for publicity purposes as associated with |
|
52 |
** Golden Code Development Corporation, FWD, or any author or contributor to |
|
53 |
** the covered work, without written authorization. |
|
54 |
** |
|
55 |
** 3. No Misrepresentation of Source or Origin. |
|
56 |
** |
|
57 |
** You may not represent the covered work as solely your work. All modified |
|
58 |
** versions of the covered work must be marked in a reasonable way to make it |
|
59 |
** clear that the modified work is not originating from Golden Code Development |
|
60 |
** Corporation or FWD. All modified versions must contain the notices of |
|
61 |
** attribution required in this license. |
|
62 |
*/ |
|
63 | ||
64 |
package com.goldencode.p2j.persist.dialect; |
|
65 | ||
66 |
import java.sql.*; |
|
67 |
import org.slf4j.*; |
|
68 |
import com.goldencode.p2j.*; |
|
69 |
import com.mchange.v2.c3p0.*; |
|
70 | ||
71 |
/** |
|
72 |
* Customizes the connection to database by setting up the {@code use.java.udfs} and {@code fwd.version} |
|
73 |
* SQL configuration variable. |
|
74 |
*/ |
|
75 |
public class FWDMariaDBConnectionCustomizer |
|
76 |
extends AbstractConnectionCustomizer |
|
77 |
{ |
|
78 |
/** Logger */ |
|
79 |
private static final Logger LOG = LoggerFactory.getLogger(FWDPostgreSQLConnectionCustomizer.class); |
|
80 |
|
|
81 |
/** |
|
82 |
* Called immediately after a {@code Connection} is acquired from the underlying database for |
|
83 |
* incorporation into the pool. |
|
84 |
* |
|
85 |
* @param c |
|
86 |
* Connection to be customized. |
|
87 |
* @param parentDataSourceIdentityToken |
|
88 |
* The parent data source identity token. |
|
89 |
*/ |
|
90 |
@Override |
|
91 |
public void onAcquire(Connection c, String parentDataSourceIdentityToken) |
|
92 |
throws java.lang.Exception |
|
93 |
{ |
|
94 |
// The database session user should be able to create temporary tables |
|
95 |
// This can be granted by GRANT CREATE TEMPORARY TABLES ON *.* TO 'fwd_user'@'%'; |
|
96 |
try |
|
97 |
{ |
|
98 |
c.prepareStatement( |
|
99 |
"create temporary table if not exists " |
|
100 |
+ "temp_error_stack(" |
|
101 |
+ "id integer not null auto_increment, " |
|
102 |
+ "state boolean not null, " |
|
103 |
+ "fwd_error_ctx text default @fwd_error_ctx, " |
|
104 |
+ "PRIMARY KEY (id)" |
|
105 |
+ ")" |
|
106 |
).executeUpdate(); |
|
107 |
} |
|
108 |
catch(SQLException e) |
|
109 |
{ |
|
110 |
LOG.warn("Failed to customize connection", e); |
|
111 |
} |
|
112 |
} |
|
113 |
} |
src/com/goldencode/p2j/persist/dialect/FWDPostgreSQLConnectionCustomizer.java 2023-02-08 16:19:49 +0000 | ||
---|---|---|
1 | 1 |
/* |
2 |
** Module : FWDConnectionCustomizer.java |
|
2 |
** Module : FWDPostgreSQLConnectionCustomizer.java
|
|
3 | 3 |
** Abstract : c3p0 connection customizer |
4 | 4 |
** |
5 |
** Copyright (c) 2021-2022, Golden Code Development Corporation.
|
|
5 |
** Copyright (c) 2021-2023, Golden Code Development Corporation.
|
|
6 | 6 |
** |
7 | 7 |
** -#- -I- --Date-- ---------------------------------------Description--------------------------------------- |
8 | 8 |
** 001 IAS 20210803 Created initial version. |
9 | 9 |
** OM 20220721 Added copyright statement, javadoc and updated formatting to GC standard. |
10 |
* IAS 20230202 Renamed |
|
10 | 11 |
*/ |
11 | 12 | |
12 | 13 |
/* |
... | ... | |
73 | 74 |
* Customizes the connection to database by setting up the {@code use.java.udfs} and {@code fwd.version} |
74 | 75 |
* SQL configuration variable. |
75 | 76 |
*/ |
76 |
public class FWDConnectionCustomizer |
|
77 |
public class FWDPostgreSQLConnectionCustomizer
|
|
77 | 78 |
extends AbstractConnectionCustomizer |
78 | 79 |
{ |
79 | 80 |
/** Logger */ |
80 |
private static final Logger LOG = LoggerFactory.getLogger(FWDConnectionCustomizer.class); |
|
81 |
private static final Logger LOG = LoggerFactory.getLogger(FWDPostgreSQLConnectionCustomizer.class);
|
|
81 | 82 |
|
82 | 83 |
/** |
83 | 84 |
* Called immediately after a {@code Connection} is acquired from the underlying database for |
src/com/goldencode/p2j/persist/dialect/MariaDbLenientDialect.java 2023-02-12 15:00:42 +0000 | ||
---|---|---|
14 | 14 |
** BS 20230126 Added support for SAVE CACHE. |
15 | 15 |
** ECF 20230127 Data type adjustment for SAVE CACHE. |
16 | 16 |
** OM 20230131 Code cleanup. |
17 |
** IAS 20230208 Added error handler support. |
|
17 | 18 |
*/ |
18 | 19 | |
19 | 20 |
/* |
... | ... | |
78 | 79 |
import com.goldencode.p2j.persist.sequence.*; |
79 | 80 |
import com.goldencode.p2j.util.*; |
80 | 81 |
import com.goldencode.p2j.util.ErrorManager.*; |
82 |
import com.mchange.v2.c3p0.*; |
|
83 | ||
81 | 84 |
import java.io.*; |
82 | 85 |
import java.sql.*; |
83 | 86 |
import java.sql.Date; |
... | ... | |
479 | 482 |
} |
480 | 483 |
|
481 | 484 |
/** |
485 |
* Get c3p0 ConnectionCustomizer class for the dialect. |
|
486 |
* @param <T> |
|
487 |
* Customizer class |
|
488 |
* @param cfg |
|
489 |
* Database configuration. |
|
490 |
* @return c3p0 ConnectionCustomizer class for the dialect. |
|
491 |
*/ |
|
492 |
@Override |
|
493 |
public Class<? extends AbstractConnectionCustomizer> connectionCustomizer(DatabaseConfig cfg) |
|
494 |
{ |
|
495 |
return FWDMariaDBConnectionCustomizer.class; |
|
496 |
} |
|
497 |
|
|
498 |
/** |
|
499 |
* Activate error handler at the database side. |
|
500 |
* @param conn |
|
501 |
* Database connection |
|
502 |
* @throws SQLException |
|
503 |
* on error. |
|
504 |
*/ |
|
505 |
@Override |
|
506 |
public void activateErrorHandler(Connection conn) |
|
507 |
throws SQLException |
|
508 |
{ |
|
509 |
conn.prepareCall("{ call activateErrorHandler()}").executeUpdate(); |
|
510 |
} |
|
511 |
|
|
512 |
/** |
|
513 |
* Reset error handler at the database side. |
|
514 |
* @param conn |
|
515 |
* Database connection |
|
516 |
* @throws SQLException |
|
517 |
* on error. |
|
518 |
*/ |
|
519 |
@Override |
|
520 |
public void resetErrorHandler(Connection conn) |
|
521 |
throws SQLException |
|
522 |
{ |
|
523 |
conn.prepareCall("{ call resetErrorHandler()}").executeUpdate(); |
|
524 |
} |
|
525 | ||
526 |
/** |
|
482 | 527 |
* Get a new instance of a splitter for DDL scripts. Reuses the splitter for PG dialect. |
483 | 528 |
* |
484 | 529 |
* @return A new instance of splitter for DDL scripts. |
... | ... | |
609 | 654 |
return true; |
610 | 655 |
} |
611 | 656 |
|
657 |
/** |
|
658 |
* Get name of the checkError UDF. |
|
659 |
* @return the name of the checkError UDF. |
|
660 |
*/ |
|
661 |
@Override |
|
662 |
public String checkErrorFn() |
|
663 |
{ |
|
664 |
return "checkError_BB"; |
|
665 |
} |
|
666 | ||
667 |
/** |
|
668 |
* Get name of the initError UDF. |
|
669 |
* @return the name of the initError UDF. |
|
670 |
*/ |
|
671 |
@Override |
|
672 |
public String initErrorFn() |
|
673 |
{ |
|
674 |
return "initError_B"; |
|
675 |
} |
|
676 | ||
612 | 677 |
/** |
613 | 678 |
* Check if the exception was caused by an error in UDF. |
614 | 679 |
* |
src/com/goldencode/p2j/persist/dialect/P2JPostgreSQLDialect.java 2023-02-12 15:00:56 +0000 | ||
---|---|---|
123 | 123 |
** OM 20221026 Excluded table name from index name by default. It will be added as needed by |
124 | 124 |
** dialects. |
125 | 125 |
** RAA 20230109 Overrided method getSequenceSetValString(). |
126 |
** IAS 20230208 Dialect-specific error handler support. |
|
126 | 127 |
*/ |
127 | 128 | |
128 | 129 |
/* |
... | ... | |
196 | 197 |
import com.goldencode.p2j.util.LogHelper; |
197 | 198 |
import com.goldencode.p2j.util.ErrorManager.*; |
198 | 199 |
import com.goldencode.util.*; |
200 |
import com.mchange.v2.c3p0.*; |
|
199 | 201 |
import com.goldencode.p2j.cfg.*; |
200 | 202 |
import com.goldencode.p2j.convert.*; |
201 | 203 |
import com.goldencode.p2j.directory.DirectoryService; |
... | ... | |
2032 | 2034 |
} |
2033 | 2035 |
|
2034 | 2036 |
/** |
2037 |
* Get c3p0 ConnectionCustomizer class for the dialect. |
|
2038 |
* @param <T> |
|
2039 |
* Customizer class |
|
2040 |
* @param cfg |
|
2041 |
* Database configuration. |
|
2042 |
* @return c3p0 ConnectionCustomizer class for the dialect. |
|
2043 |
*/ |
|
2044 |
@Override |
|
2045 |
public Class<? extends AbstractConnectionCustomizer> connectionCustomizer(DatabaseConfig cfg) |
|
2046 |
{ |
|
2047 |
return cfg.isUseJavaUDFs() ? null : FWDPostgreSQLConnectionCustomizer.class; |
|
2048 |
} |
|
2049 |
/** |
|
2035 | 2050 |
* Worker method for {@code generateTriggerDDLs()}. It generates the DDLs needed to create all |
2036 | 2051 |
* triggers in a database with a specific schema and using a certain dialect. |
2037 | 2052 |
* |
src/com/goldencode/p2j/persist/dialect/P2JSQLServer2008Dialect.java 2023-02-12 15:01:53 +0000 | ||
---|---|---|
43 | 43 |
** RAA 20230109 Overrided method getSequenceSetValString(). |
44 | 44 |
** SVL 20230110 P2JIndex.components() provides direct access to the components array in order to improve |
45 | 45 |
** performance. |
46 |
** IAS 20230208 Dialect-specific error handler support. |
|
46 | 47 |
*/ |
47 | 48 | |
48 | 49 |
/* |
... | ... | |
1363 | 1364 |
return false; |
1364 | 1365 |
} |
1365 | 1366 | |
1367 |
/** |
|
1368 |
* Get name of the checkError UDF. |
|
1369 |
* @return the name of the checkError UDF. |
|
1370 |
*/ |
|
1371 |
@Override |
|
1372 |
public String checkErrorFn() |
|
1373 |
{ |
|
1374 |
return "dbo.checkError_bb"; |
|
1375 |
} |
|
1376 | ||
1377 |
/** |
|
1378 |
* Get name of the initError UDF. |
|
1379 |
* @return the name of the initError UDF. |
|
1380 |
*/ |
|
1381 |
@Override |
|
1382 |
public String initErrorFn() |
|
1383 |
{ |
|
1384 |
return "dbo.initError_b"; |
|
1385 |
} |
|
1386 | ||
1366 | 1387 |
/** |
1367 | 1388 |
* Check if the exception was caused by error in UDF. |
1368 | 1389 |
* @param e |
src/com/goldencode/p2j/persist/orm/FqlToSqlConverter.java 2023-02-12 15:02:55 +0000 | ||
---|---|---|
47 | 47 |
** SVL 20230108 Improved performance by replacing some "for-each" loops with indexed "for" loops. |
48 | 48 |
** 20221031 Collected fields of "select" query. |
49 | 49 |
** 20221101 Fixed possible NPE. |
50 |
** IAS 20230208 Dialect-specific error handler support. |
|
50 | 51 |
*/ |
51 | 52 | |
52 | 53 |
/* |
... | ... | |
271 | 272 |
* Mutable session attributes' values used in the query |
272 | 273 |
*/ |
273 | 274 |
private final List<SessionAttr> sessionAttrs = new ArrayList<>(); |
275 | ||
276 |
/** The name of the checkError UDF with prepended dot */ |
|
277 |
private final String _checkErrorFn; |
|
278 |
|
|
279 |
/** Flag indicating that the query contains error handling */ |
|
280 |
private boolean containsErrorHandling = false; |
|
281 | ||
274 | 282 |
|
275 | 283 |
/** |
276 | 284 |
* The constructor is private. To create an instance of this class, use the {@code getInstance} |
... | ... | |
296 | 304 |
this.generateUniqueSqlColumnNames = true; |
297 | 305 |
this.useWordTables = !SchemaDictionary.TEMP_TABLE_DB.equals(schema) && |
298 | 306 |
!db.isDirty() && !db.isMeta() && dialect.useWordTables(); |
307 |
this._checkErrorFn = "." + dialect.checkErrorFn(); |
|
299 | 308 |
} |
300 | 309 |
|
301 | 310 |
/** |
... | ... | |
347 | 356 |
{ |
348 | 357 |
return sessionAttrs; |
349 | 358 |
} |
359 | ||
360 |
/** |
|
361 |
* Checks if the query contains error handling. |
|
362 |
* |
|
363 |
* @return {@code true} if the query contains error handling. |
|
364 |
*/ |
|
365 |
public boolean containsErrorHandling() |
|
366 |
{ |
|
367 |
return containsErrorHandling; |
|
368 |
} |
|
350 | 369 |
/** |
351 | 370 |
* Check if the query reads _UserTableStat VST. |
352 | 371 |
* |
... | ... | |
2481 | 2500 |
} |
2482 | 2501 |
else |
2483 | 2502 |
{ |
2503 |
if (text.equals(dialect.checkErrorFn()) || text.endsWith(_checkErrorFn)) |
|
2504 |
{ |
|
2505 |
containsErrorHandling = true; |
|
2506 |
} |
|
2484 | 2507 |
sb.append(text); |
2485 | 2508 |
sb.append("("); |
2486 | 2509 |
if (next.getNumImmediateChildren() == 0) |
src/com/goldencode/p2j/persist/orm/PooledDataSourceProvider.java 2023-02-12 15:04:54 +0000 | ||
---|---|---|
2 | 2 |
** Module : PooledDataSourceProvider.java |
3 | 3 |
** Abstract : Implementation of DataSourceProvider that offers a pooled DataSource. |
4 | 4 |
** |
5 |
** Copyright (c) 2019-2021, Golden Code Development Corporation.
|
|
5 |
** Copyright (c) 2019-2023, Golden Code Development Corporation.
|
|
6 | 6 |
** |
7 | 7 |
** -#- -I- --Date-- --------------------------------------Description---------------------------------------- |
8 | 8 |
** 001 ECF 20191001 Created initial version with basic runtime support. |
... | ... | |
11 | 11 |
** ECF 20210910 Minor cleanup. |
12 | 12 |
** IAS 20220816 Do not use ConnectionCustomizer for non-PostgreSQL databases. |
13 | 13 |
** TW 20221024 Implement support for driver_properties. |
14 |
** IAS 20230208 Dialect-specific error handler support. |
|
14 | 15 |
*/ |
15 | 16 | |
16 | 17 |
/* |
... | ... | |
191 | 192 |
} |
192 | 193 |
} |
193 | 194 |
} |
194 |
if (!cfg.isUseJavaUDFs() && |
|
195 |
(DatabaseManager.getDialect(database) instanceof P2JPostgreSQLDialect)) |
|
195 |
Class<? extends AbstractConnectionCustomizer> customizer = |
|
196 |
DatabaseManager.getDialect(database).connectionCustomizer(cfg); |
|
197 |
if (ds.getConnectionCustomizerClassName() == null && customizer != null) |
|
198 |
{ |
|
199 |
ds.setConnectionCustomizerClassName(customizer.getName()); |
|
200 |
} |
|
201 |
if (!cfg.isUseJavaUDFs() ) |
|
196 | 202 |
{ |
197 | 203 |
extensions.putIfAbsent("useJavaUdfs", "n"); |
198 |
if (ds.getConnectionCustomizerClassName() == null) |
|
199 |
{ |
|
200 |
ds.setConnectionCustomizerClassName(FWDConnectionCustomizer.class.getName()); |
|
201 |
} |
|
202 | 204 |
} |
203 | 205 |
if (!extensions.isEmpty()) |
204 | 206 |
{ |
src/com/goldencode/p2j/persist/orm/Query.java 2023-02-12 15:04:48 +0000 | ||
---|---|---|
2 | 2 |
** Module : Query.java |
3 | 3 |
** Abstract : Wrapper for FQL statements. |
4 | 4 |
** |
5 |
** Copyright (c) 2019-2022, Golden Code Development Corporation.
|
|
5 |
** Copyright (c) 2019-2023, Golden Code Development Corporation.
|
|
6 | 6 |
** |
7 | 7 |
** -#- -I- --Date-- ---------------------------------------Description--------------------------------------- |
8 | 8 |
** 001 ECF 20191001 Created initial version with stubbed methods. |
... | ... | |
26 | 26 |
** SBI 20221023 Added a usage of SQLQuery.uniqueResult(Session session, RowStructure rowStructure). |
27 | 27 |
** CA 20221031 Javadoc fixes. |
28 | 28 |
** IAS 20230209 Fixed ${TZ} placeholder value |
29 |
** IAS 20230208 Dialect-specific error handler support. |
|
29 | 30 |
*/ |
30 | 31 | |
31 | 32 |
/* |
... | ... | |
120 | 121 |
/** Flag indicating that the query reads from _Lock VST */ |
121 | 122 |
private boolean lockTableRead = false; |
122 | 123 | |
124 |
/** Flag indicating that the query contains error handling */ |
|
125 |
private boolean containsErrorHandling = false; |
|
126 |
|
|
123 | 127 |
/** |
124 | 128 |
* The maximum number of results accepted by the (SELECT) query. Used with {@code firstResult} |
125 | 129 |
* to configure result pagination. |
... | ... | |
353 | 357 |
paramCount = fql2sql.getLastConversionParamCount(); |
354 | 358 |
wasRewritten = fql2sql.isQueryWasRewritten(); |
355 | 359 |
userTableStatRead = fql2sql.isUserTableStatRead(); |
360 |
this.containsErrorHandling = fql2sql.containsErrorHandling(); |
|
356 | 361 |
lockTableRead = fql2sql.isLockTableRead(); |
357 | 362 |
if (!wasRewritten) |
358 | 363 |
{ |
359 | 364 |
cache.accept(this); |
360 | 365 |
} |
361 |
sqlQuery = Session.createSQLQuery(sql, fql2sql.sessionAttrs(), fql2sql.getParameterPermutation()); |
|
366 |
sqlQuery = Session.createSQLQuery(sql, fql2sql.sessionAttrs(), |
|
367 |
fql2sql.getParameterPermutation()). |
|
368 |
containsErrorHandling(containsErrorHandling); |
|
362 | 369 |
}; |
363 | 370 |
|
364 | 371 |
QUERY_PARSE.timer(op); |
src/com/goldencode/p2j/persist/orm/SQLQuery.java 2023-02-12 15:04:05 +0000 | ||
---|---|---|
51 | 51 |
** CA 20230104 If a cached record is incomplete, get the full record from the database when a hydrate is |
52 | 52 |
** is performed. |
53 | 53 |
** IAS 20230209 Fixed ${TZ} placeholder value |
54 |
** IAS 20230208 Dialect-specific error handler support. |
|
54 | 55 |
*/ |
55 | 56 | |
56 | 57 |
/* |
... | ... | |
172 | 173 |
/** Mutable session attributes' values used in the query. */ |
173 | 174 |
private final List<SessionAttr> sessionAttrs; |
174 | 175 |
|
176 |
/** Flag indicating that the query contains error handling */ |
|
177 |
private boolean containsErrorHandling = false; |
|
178 | ||
175 | 179 |
/** The {@code PreparedStatement}. */ |
176 | 180 |
private PreparedStatement stmt; |
177 | 181 |
|
... | ... | |
214 | 218 |
} |
215 | 219 |
|
216 | 220 |
/** |
221 |
* Set the value of the flag indicating that the query contains error handling. |
|
222 |
* @param value |
|
223 |
* The new value of the flag; |
|
224 |
* @return <code>this</code> |
|
225 |
*/ |
|
226 |
public SQLQuery containsErrorHandling(boolean value) |
|
227 |
{ |
|
228 |
this.containsErrorHandling = value; |
|
229 |
return this; |
|
230 |
} |
|
231 |
|
|
232 |
/** |
|
217 | 233 |
* Checks if the query can raise {@code SQLWarning}. |
218 | 234 |
* |
219 | 235 |
* @return {@code true} if the query can raise {@code SQLWarning}. |
... | ... | |
237 | 253 |
return this; |
238 | 254 |
} |
239 | 255 |
|
256 | ||
240 | 257 |
/** |
241 | 258 |
* Expand placeholder. |
242 | 259 |
* @param dialect |
... | ... | |
319 | 336 |
|
320 | 337 |
try |
321 | 338 |
{ |
339 |
activateErrorHandler(session); |
|
322 | 340 |
stmt = conn.prepareStatement(sql, scrollMode, readOnlyMode); |
323 | 341 |
setParameters(stmt, false); |
324 | 342 |
|
... | ... | |
332 | 350 |
|
333 | 351 |
ResultSet resultSet = resultSetArray[0]; |
334 | 352 |
reportSQLWarnings(session); |
335 |
return new ScrollableResults<>(stmt, resultSet, rowStructure, session); |
|
353 |
return new ScrollableResults<T>(stmt, resultSet, rowStructure, session). |
|
354 |
onClose(() -> {resetErrorHandler(session); return null;}); |
|
336 | 355 |
} |
337 | 356 |
catch (SQLException exc) |
338 | 357 |
{ |
... | ... | |
344 | 363 |
} |
345 | 364 |
throw new PersistenceException("Error scrolling", exc); |
346 | 365 |
} |
366 |
// finally |
|
367 |
// { |
|
368 |
// resetErrorHandler(session); |
|
369 |
// } |
|
347 | 370 |
} |
348 | 371 |
|
349 | 372 |
/** |
... | ... | |
372 | 395 |
|
373 | 396 |
try |
374 | 397 |
{ |
398 |
activateErrorHandler(session); |
|
375 | 399 |
stmt = conn.prepareStatement(sql); |
376 | 400 |
setParameters(stmt, false); |
377 | 401 |
|
... | ... | |
381 | 405 |
log(session.getDatabase(), stmt, () -> resultSetArray[0] = stmt.executeQuery()); |
382 | 406 |
|
383 | 407 |
ResultSet resultSet = resultSetArray[0]; |
384 |
return new ScrollableResults<>(stmt, resultSet, rowStructure, session); |
|
408 |
return new ScrollableResults<T>(stmt, resultSet, rowStructure, session). |
|
409 |
onClose(() -> {resetErrorHandler(session); return null;}); |
|
385 | 410 |
} |
386 | 411 |
catch (SQLException exc) |
387 | 412 |
{ |
388 | 413 |
close(); |
389 | 414 |
throw new PersistenceException("Error scrolling", exc); |
390 | 415 |
} |
416 |
// finally |
|
417 |
// { |
|
418 |
// resetErrorHandler(session); |
|
419 |
// } |
|
391 | 420 |
} |
392 | 421 |
|
393 | 422 |
/** |
... | ... | |
439 | 468 |
|
440 | 469 |
try |
441 | 470 |
{ |
471 |
activateErrorHandler(session); |
|
442 | 472 |
stmt = conn.prepareStatement(sql); |
443 | 473 |
setParameters(stmt, false); |
444 | 474 |
|
... | ... | |
489 | 519 |
finally |
490 | 520 |
{ |
491 | 521 |
close(); |
522 |
resetErrorHandler(session); |
|
492 | 523 |
} |
493 | 524 |
} |
494 | 525 |
|
... | ... | |
511 | 542 |
|
512 | 543 |
try |
513 | 544 |
{ |
545 |
activateErrorHandler(session); |
|
514 | 546 |
stmt = conn.prepareStatement(sql); |
515 | 547 |
setParameters(stmt, true); |
516 | 548 |
|
... | ... | |
529 | 561 |
finally |
530 | 562 |
{ |
531 | 563 |
close(); |
564 |
resetErrorHandler(session); |
|
532 | 565 |
} |
533 | 566 |
} |
534 | 567 |
|
... | ... | |
562 | 595 |
|
563 | 596 |
try |
564 | 597 |
{ |
598 |
activateErrorHandler(session); |
|
565 | 599 |
int rowSize = rowStructure.size(); |
566 | 600 |
List<T> ret = new ArrayList<>(); |
567 | 601 |
stmt = conn.prepareStatement(sql); |
... | ... | |
640 | 674 |
} |
641 | 675 |
finally |
642 | 676 |
{ |
677 |
resetErrorHandler(session); |
|
643 | 678 |
close(); |
644 | 679 |
} |
645 | 680 |
} |
... | ... | |
1022 | 1057 |
} |
1023 | 1058 |
|
1024 | 1059 |
/** |
1060 |
* Activate error handler at the database side. |
|
1061 |
* @param session |
|
1062 |
* Database session |
|
1063 |
* @throws SQLException |
|
1064 |
* on error. |
|
1065 |
* @throws PersistenceException |
|
1066 |
* on error. |
|
1067 |
*/ |
|
1068 |
private void activateErrorHandler(Session session) |
|
1069 |
throws SQLException, PersistenceException |
|
1070 |
{ |
|
1071 |
if (!containsErrorHandling) |
|
1072 |
{ |
|
1073 |
return; |
|
1074 |
} |
|
1075 |
Query.getDialect(session).activateErrorHandler(session.getConnection()); |
|
1076 |
} |
|
1077 |
|
|
1078 |
/** |
|
1079 |
* Reset error handler at the database side. |
|
1080 |
* @param session |
|
1081 |
* Database session |
|
1082 |
* @throws SQLException |
|
1083 |
* on error. |
|
1084 |
* @throws PersistenceException |
|
1085 |
* on error. |
|
1086 |
*/ |
|
1087 |
public void resetErrorHandler(Session session) |
|
1088 |
throws PersistenceException |
|
1089 |
{ |
|
1090 |
if (!containsErrorHandling) |
|
1091 |
{ |
|
1092 |
return; |
|
1093 |
} |
|
1094 |
try |
|
1095 |
{ |
|
1096 |
Query.getDialect(session).activateErrorHandler(session.getConnection()); |
|
1097 |
} |
|
1098 |
catch (SQLException e) |
|
1099 |
{ |
|
1100 |
throw new PersistenceException("Failed to reset error handler", e); |
|
1101 |
} |
|
1102 |
} |
|
1103 |
/** |
|
1025 | 1104 |
* Sets the value for a parameter at a specified position in a statement. The process is done in recursive |
1026 | 1105 |
* manner for arrays and {@code List}s. The {@code pos} is incremented automatically for each scalar |
1027 | 1106 |
* parameter configured. |
src/com/goldencode/p2j/persist/orm/ScrollableResults.java 2023-02-12 15:04:30 +0000 | ||
---|---|---|
2 | 2 |
** Module : ScrollableResults.java |
3 | 3 |
** Abstract : Allows scrollable access to result set. |
4 | 4 |
** |
5 |
** Copyright (c) 2019-2022, Golden Code Development Corporation.
|
|
5 |
** Copyright (c) 2019-2023, Golden Code Development Corporation.
|
|
6 | 6 |
** |
7 | 7 |
** -#- -I- --Date-- ---------------------------------Description--------------------------------- |
8 | 8 |
** 001 ECF 20191001 Created initial version, with stubbed methods. |
9 | 9 |
** OM 20191111 Added method implementation. |
10 | 10 |
** 002 SBI 20220811 Added new version of get method to retrieve selected columns from a row. |
11 | 11 |
** 20221023 Added a usage of SQLQuery.hydrateRecord(ResultSet, RowStructure, int, Session). |
12 |
** IAS 20230208 Dialect-specific error handler support. |
|
12 | 13 |
*/ |
13 | 14 | |
14 | 15 |
/* |
... | ... | |
96 | 97 |
/** The {@code Session} to be used.*/ |
97 | 98 |
private final Session session; |
98 | 99 |
|
100 |
/** On close hook*/ |
|
101 |
private SandboxRun<Void> onClose = () -> null; |
|
102 |
|
|
99 | 103 |
/** |
100 | 104 |
* Constructs a {@code ScrollableResults} object for further use. |
101 | 105 |
* |
... | ... | |
129 | 133 |
} |
130 | 134 |
|
131 | 135 |
/** |
136 |
* Set on close hook |
|
137 |
* @param hook |
|
138 |
* new hook; |
|
139 |
* @return <code>this</code> |
|
140 |
*/ |
|
141 |
public ScrollableResults<T> onClose(SandboxRun<Void> hook) |
|
142 |
{ |
|
143 |
this.onClose = hook; |
|
144 |
return this; |
|
145 |
} |
|
146 |
/** |
|
132 | 147 |
* Go to result row. |
133 | 148 |
* |
134 | 149 |
* @return {@code true} if there is a result under the cursor and {@code false} otherwise |
... | ... | |
339 | 354 | |
340 | 355 |
/** |
341 | 356 |
* Obtain the value of a {@code i}-th column of the current row. |
357 |
* @param i |
|
358 |
* column number |
|
359 |
* @param tClass |
|
360 |
* column |
|
342 | 361 |
* |
343 | 362 |
* @return The value on {@code i}-th column of the current row if {@code i} and current row |
344 | 363 |
* are valid and {@code null} otherwise. |
345 | 364 |
*/ |
346 |
public T get(int i, Class<T> tClass)
|
|
365 |
public T get(int i, Class<T>tClass) |
|
347 | 366 |
{ |
348 | 367 |
return execute(() -> rs.getObject(i + 1, tClass), null); |
349 | 368 |
} |
... | ... | |
409 | 428 |
public void close() |
410 | 429 |
throws PersistenceException |
411 | 430 |
{ |
412 |
execute(() -> { stmt.close(); return null; }, null); |
|
431 |
execute(() -> { stmt.close(); onClose.run(); return null; }, null);
|
|
413 | 432 |
} |
414 | 433 |
|
415 | 434 |
/** |
udf/mariadb/error_handler.sql 2023-02-12 14:29:52 +0000 | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
** Module : error-handlers.sql |
3 |
** Abstract : 'Native' versions of the ErrorHandler-based Java UDFs |
|
3 |
** Abstract : 'Native' versions of the ErrorHandler-based Java UDFs (MariaDB version)
|
|
4 | 4 |
** |
5 |
** Copyright (c) 2021, Golden Code Development Corporation.
|
|
5 |
** Copyright (c) 2023, Golden Code Development Corporation.
|
|
6 | 6 |
** |
7 | 7 |
** -#- -I- --Date-- --------------------------------Description---------------------------------- |
8 |
** 001 IAS 20210803 Created initial version.
|
|
8 |
** 001 IAS 20230208 Created initial version.
|
|
9 | 9 |
*/ |
10 | 10 |
/* |
11 | 11 |
** This program is free software: you can redistribute it and/or modify |
... | ... | |
62 | 62 |
/** |
63 | 63 |
* Check if the error stack is active |
64 | 64 |
*/ |
65 |
##CREATE OR REPLACE FUNCTION udf.error_handler_active() |
|
66 |
CREATE OR REPLACE FUNCTION error_handler_active() ##!! TODO |
|
67 |
##RETURNS boolean |
|
65 |
CREATE OR REPLACE FUNCTION error_handler_active() |
|
68 | 66 |
RETURNS BOOLEAN |
69 | 67 |
DETERMINISTIC |
70 | 68 |
BEGIN |
71 |
RETURN null;
|
|
69 |
RETURN true; -- exists(select * from temp_error_stack where fwd_error_ctx = @fwd_error_ctx);
|
|
72 | 70 |
END; |
73 | 71 |
$$ |
74 | 72 | |
75 |
##AS $function$ |
|
76 |
##select exists ( |
|
77 |
## select 1 |
|
78 |
## from information_schema.tables |
|
79 |
## where table_schema like 'pg_temp_%' |
|
80 |
## and table_name='temp_error_stack' |
|
81 |
##) |
|
82 |
##$function$ |
|
83 | 73 | |
84 | 74 |
/** |
85 | 75 |
* A special wrapper function for a UDF called |
... | ... | |
118 | 108 |
* @return false if an error occurred in this scope; |
119 | 109 |
* otherwise, the result of the boolean sub-expression. |
120 | 110 |
*/ |
121 |
##CREATE OR REPLACE FUNCTION udf.initerror(state boolean) |
|
122 |
CREATE OR REPLACE FUNCTION initerror_B(state BOOLEAN) ##!! TODO |
|
123 |
##RETURNS boolean |
|
111 |
CREATE OR REPLACE FUNCTION initError_B(state BOOLEAN) |
|
124 | 112 |
RETURNS BOOLEAN |
125 | 113 |
DETERMINISTIC |
126 | 114 |
BEGIN |
127 |
RETURN null; |
|
115 |
call initError_P(state); |
|
116 |
return true; |
|
128 | 117 |
END; |
129 | 118 |
$$ |
130 | 119 | |
131 |
##AS $function$ |
|
132 |
##begin |
|
133 |
## if not udf.error_handler_active() then |
|
134 |
## create temporary table if not exists temp_error_stack(id serial, state boolean not null) on commit drop; |
|
135 |
## end if; |
|
136 |
## insert into temp_error_stack(state) values (state); |
|
137 |
## return true; |
|
138 |
##end; |
|
139 |
##$function$ |
|
120 |
CREATE OR REPLACE PROCEDURE initError_P(state BOOLEAN) |
|
121 |
DETERMINISTIC |
|
122 |
BEGIN |
|
123 |
insert into temp_error_stack(state,fwd_error_ctx) values (state, @fwd_error_ctx); |
|
124 |
END; |
|
125 |
$$ |
|
140 | 126 | |
141 | 127 |
/** |
142 | 128 |
* Initialize the error flag stack for the current function scope by |
... | ... | |
147 | 133 |
* |
148 | 134 |
* @return Boolean.TRUE. |
149 | 135 |
*/ |
150 |
##CREATE OR REPLACE FUNCTION udf.checkerror(init boolean, result boolean) |
|
151 |
CREATE OR REPLACE FUNCTION checkerror_BB(init BOOLEAN, result BOOLEAN) ##!! TODO |
|
152 |
##RETURNS boolean |
|
136 |
CREATE OR REPLACE FUNCTION checkError_BB(init BOOLEAN, result BOOLEAN) |
|
153 | 137 |
RETURNS BOOLEAN |
154 | 138 |
DETERMINISTIC |
155 | 139 |
BEGIN |
156 |
RETURN null; |
|
157 |
END; |
|
158 |
$$ |
|
159 | ||
160 |
##AS $function$ |
|
161 |
##declare top bigint; |
|
162 |
##declare val boolean; |
|
163 |
##begin |
|
164 |
## if not udf.error_handler_active() then |
|
165 |
## create temporary table if not exists temp_error_stack(id serial, state boolean not null) on commit drop; |
|
166 |
## end if; |
|
167 |
## top := (select max(id) from temp_error_stack); |
|
168 |
## if top is null then |
|
169 |
## return null; |
|
170 |
##-- raise exception 'Error stack is empty'; |
|
171 |
## end if; |
|
172 |
## val := (select state from temp_error_stack where id = top); |
|
173 |
## delete from temp_error_stack where id = top; |
|
174 |
## return case when val then false else result end; |
|
175 |
##end; |
|
176 |
##$function$ |
|
140 |
declare top integer; |
|
141 |
declare val boolean; |
|
142 |
set top = (select max(id) from temp_error_stack); |
|
143 |
if top is null then |
|
144 |
return null; |
|
145 |
end if; |
|
146 |
set val = (select state from temp_error_stack where id = top); |
|
147 |
delete from temp_error_stack where id = top; |
|
148 |
return if(val, false, result); |
|
149 |
END; |
|
150 |
$$ |
|
151 | ||
152 |
/** |
|
153 |
* Activate error handler |
|
154 |
*/ |
|
155 |
CREATE OR REPLACE PROCEDURE activateErrorHandler() |
|
156 |
DETERMINISTIC |
|
157 |
begin |
|
158 |
truncate table temp_error_stack; |
|
159 |
set @fwd_error_ctx = uuid(); |
|
160 |
END; |
|
161 |
$$ |
|
162 | ||
163 |
/** |
|
164 |
* Reset error handler |
|
165 |
*/ |
|
166 |
CREATE OR REPLACE PROCEDURE resetErrorHandler() |
|
167 |
DETERMINISTIC |
|
168 |
begin |
|
169 |
truncate table temp_error_stack; |
|
170 |
set @fwd_error_ctx = null; |
|
171 |
END; |
|
172 |
$$ |
|
177 | 173 |
udf/mariadb/guard.awk 2023-02-12 13:38:24 +0000 | ||
---|---|---|
1 |
# Module : guard.awk |
|
2 |
# Abstract : awk script for generating 'guarded' versions of the MariaDB UDFs |
|
3 |
# |
|
4 |
# Copyright (c) 2023, Golden Code Development Corporation. |
|
5 |
# |
|
6 |
# -#- -I- --Date-- --------------------------------Description---------------------------------- |
|
7 |
# 001 IAS 20230308 Created initial version. |
|
8 |
# |
|
9 |
# This program is free software: you can redistribute it and/or modify |
|
10 |
# it under the terms of the GNU Affero General Public License as |
|
11 |
# published by the Free Software Foundation, either version 3 of the |
|
12 |
# License, or (at your option) any later version. |
|
13 |
# |
|
14 |
# This program is distributed in the hope that it will be useful, |
|
15 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
# GNU Affero General Public License for more details. |
|
18 |
# |
|
19 |
# You may find a copy of the GNU Affero GPL version 3 at the following |
|
20 |
# location: https://www.gnu.org/licenses/agpl-3.0.en.html |
|
21 |
# |
|
22 |
# Additional terms under GNU Affero GPL version 3 section 7: |
|
23 |
# |
|
24 |
# Under Section 7 of the GNU Affero GPL version 3, the following additional |
|
25 |
# terms apply to the works covered under the License. These additional terms |
|
26 |
# are non-permissive additional terms allowed under Section 7 of the GNU |
|
27 |
# Affero GPL version 3 and may not be removed by you. |
|
28 |
# |
|
29 |
# 0. Attribution Requirement. |
|
30 |
# |
|
31 |
# You must preserve all legal notices or author attributions in the covered |
|
32 |
# work or Appropriate Legal Notices displayed by works containing the covered |
|
33 |
# work. You may not remove from the covered work any author or developer |
|
34 |
# credit already included within the covered work. |
|
35 |
# |
|
36 |
# 1. No License To Use Trademarks. |
|
37 |
# |
|
38 |
# This license does not grant any license or rights to use the trademarks |
|
39 |
# Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks |
|
40 |
# of Golden Code Development Corporation. You are not authorized to use the |
|
41 |
# name Golden Code, FWD, or the names of any author or contributor, for |
|
42 |
# publicity purposes without written authorization. |
|
43 |
# |
|
44 |
# 2. No Misrepresentation of Affiliation. |
|
45 |
# |
|
46 |
# You may not represent yourself as Golden Code Development Corporation or FWD. |
|
47 |
# |
|
48 |
# You may not represent yourself for publicity purposes as associated with |
|
49 |
# Golden Code Development Corporation, FWD, or any author or contributor to |
|
50 |
# the covered work, without written authorization. |
|
51 |
# |
|
52 |
# 3. No Misrepresentation of Source or Origin. |
|
53 |
# |
|
54 |
# You may not represent the covered work as solely your work. All modified |
|
55 |
# versions of the covered work must be marked in a reasonable way to make it |
|
56 |
# clear that the modified work is not originating from Golden Code Development |
|
57 |
# Corporation or FWD. All modified versions must contain the notices of |
|
58 |
# attribution required in this license. |
|
59 | ||
60 |
# Generates 'guarded' versions of the UDFs |
|
61 |
# Usage: awk -f guard.awk <udfs.sql >guarded.sql |
|
62 | ||
63 |
BEGIN { |
|
64 |
print "-- The 'guarded' versions of SQL UDFs"; |
|
65 |
print "-- Generated automatically from udfs.sql with guard.awk script."; |
|
66 |
print "-- DO NOT MODIFY!"; |
|
67 |
} |
|
68 | ||
69 |
/\/\*/, /\*\// { |
|
70 |
print $0; |
|
71 |
} |
|
72 | ||
73 |
match($0, "^CREATE *OR *REPLACE *FUNCTION *(.*)$", m) { |
|
74 |
f = m[1]; |
|
75 |
print "create or replace function guarded_" f; |
|
76 |
} |
|
77 |
/^RETURNS/ { |
|
78 |
print tolower($0); |
|
79 |
s = f; |
|
80 |
gsub(/\(50, 10\)/, "", s); |
|
81 |
gsub(/\(3\)/, "", s); |
|
82 |
gsub(/ JSON/, "", s); |
|
83 |
gsub(/ [a-zA-Z]*\)/, ")", s); |
|
84 |
gsub(/ [^,]*, */, ", ", s); |
|
85 |
gsub(/##!! TODO/, "", s); |
|
86 |
print "deterministic"; |
|
87 |
print "begin"; |
|
88 |
print "declare tmp text;" |
|
89 |
print "declare exit handler for SQLEXCEPTION"; |
|
90 |
print " begin"; |
|
91 |
print " GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;"; |
|
92 |
print " set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text);"; |
|
93 |
print " if error_handler_active() then"; |
|
94 |
print " call initError_P(true);"; |
|
95 |
print " signal sqlstate '01FWD' set message_text = tmp;"; |
|
96 |
print " return null;"; |
|
97 |
print " else"; |
|
98 |
print " signal sqlstate 'FWD00' set message_text = tmp;"; |
|
99 |
print " end if;"; |
|
100 |
print " end;"; |
|
101 |
print " return " s ";"; |
|
102 |
print "end;"; |
|
103 |
print "$$"; |
|
104 |
} |
udf/mariadb/guarded.sql 2023-02-12 13:42:03 +0000 | ||
---|---|---|
1 |
-- The 'guarded' versions of SQL UDFs |
|
2 |
-- Generated automatically from udfs.sql with guard.awk script. |
|
3 |
-- DO NOT MODIFY! |
|
4 |
/* |
|
5 |
** Module : udfs.sql |
|
6 |
** Abstract : 'native' versions of the Java UDFs for MariaDB |
|
7 |
** |
|
8 |
** Copyright (c) 2022, Golden Code Development Corporation. |
|
9 |
** |
|
10 |
** -#- -I- --Date-- --------------------------------Description---------------------------------- |
|
11 |
** 001 IAS 20220810 Created UDFs' templates. |
|
12 |
*/ |
|
13 |
/* |
|
14 |
** This program is free software: you can redistribute it and/or modify |
|
15 |
** it under the terms of the GNU Affero General Public License as |
|
16 |
** published by the Free Software Foundation, either version 3 of the |
|
17 |
** License, or (at your option) any later version. |
|
18 |
** |
|
19 |
** This program is distributed in the hope that it will be useful, |
|
20 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
21 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
22 |
** GNU Affero General Public License for more details. |
|
23 |
** |
|
24 |
** You may find a copy of the GNU Affero GPL version 3 at the following |
|
25 |
** location: https://www.gnu.org/licenses/agpl-3.0.en.html |
|
26 |
** |
|
27 |
** Additional terms under GNU Affero GPL version 3 section 7: |
|
28 |
** |
|
29 |
** Under Section 7 of the GNU Affero GPL version 3, the following additional |
|
30 |
** terms apply to the works covered under the License. These additional terms |
|
31 |
** are non-permissive additional terms allowed under Section 7 of the GNU |
|
32 |
** Affero GPL version 3 and may not be removed by you. |
|
33 |
** |
|
34 |
** 0. Attribution Requirement. |
|
35 |
** |
|
36 |
** You must preserve all legal notices or author attributions in the covered |
|
37 |
** work or Appropriate Legal Notices displayed by works containing the covered |
|
38 |
** work. You may not remove from the covered work any author or developer |
|
39 |
** credit already included within the covered work. |
|
40 |
** |
|
41 |
** 1. No License To Use Trademarks. |
|
42 |
** |
|
43 |
** This license does not grant any license or rights to use the trademarks |
|
44 |
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks |
|
45 |
** of Golden Code Development Corporation. You are not authorized to use the |
|
46 |
** name Golden Code, FWD, or the names of any author or contributor, for |
|
47 |
** publicity purposes without written authorization. |
|
48 |
** |
|
49 |
** 2. No Misrepresentation of Affiliation. |
|
50 |
** |
|
51 |
** You may not represent yourself as Golden Code Development Corporation or FWD. |
|
52 |
** |
|
53 |
** You may not represent yourself for publicity purposes as associated with |
|
54 |
** Golden Code Development Corporation, FWD, or any author or contributor to |
|
55 |
** the covered work, without written authorization. |
|
56 |
** |
|
57 |
** 3. No Misrepresentation of Source or Origin. |
|
58 |
** |
|
59 |
** You may not represent the covered work as solely your work. All modified |
|
60 |
** versions of the covered work must be marked in a reasonable way to make it |
|
61 |
** clear that the modified work is not originating from Golden Code Development |
|
62 |
** Corporation or FWD. All modified versions must contain the notices of |
|
63 |
** attribution required in this license. |
|
64 |
*/ |
|
65 |
/** |
|
66 |
* For debugging. |
|
67 |
* See the commented table definition above |
|
68 |
*/ |
|
69 |
/** |
|
70 |
* Convert 4GL 'matches' pattern to regex |
|
71 |
*/ |
|
72 |
create or replace function guarded_regex_tb(s TEXT, windows BOOLEAN) |
|
73 |
returns text |
|
74 |
deterministic |
|
75 |
begin |
|
76 |
declare tmp text; |
|
77 |
declare exit handler for SQLEXCEPTION |
|
78 |
begin |
|
79 |
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; |
|
80 |
set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text); |
|
81 |
if error_handler_active() then |
|
82 |
call initError_P(true); |
|
83 |
signal sqlstate '01FWD' set message_text = tmp; |
|
84 |
return null; |
|
85 |
else |
|
86 |
signal sqlstate 'FWD00' set message_text = tmp; |
|
87 |
end if; |
|
88 |
end; |
|
89 |
return regex_tb(s, windows); |
|
90 |
end; |
|
91 |
$$ |
|
92 |
/** |
|
93 |
* Convert 4GL 'CAN-DO' function pattern to regex |
|
94 |
*/ |
|
95 |
create or replace function guarded_regex_t(s TEXT) |
|
96 |
returns text |
|
97 |
deterministic |
|
98 |
begin |
|
99 |
declare tmp text; |
|
100 |
declare exit handler for SQLEXCEPTION |
|
101 |
begin |
|
102 |
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; |
|
103 |
set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text); |
|
104 |
if error_handler_active() then |
|
105 |
call initError_P(true); |
|
106 |
signal sqlstate '01FWD' set message_text = tmp; |
|
107 |
return null; |
|
108 |
else |
|
109 |
signal sqlstate 'FWD00' set message_text = tmp; |
|
110 |
end if; |
|
111 |
end; |
|
112 |
return regex_t(s); |
|
113 |
end; |
|
114 |
$$ |
|
115 |
/** |
|
116 |
* Transform the given integer into a string as the time value |
|
117 |
*/ |
|
118 |
create or replace function guarded_totimestring_lti(v BIGINT, fmt TEXT, tz INTEGER) |
|
119 |
returns text |
|
120 |
deterministic |
|
121 |
begin |
|
122 |
declare tmp text; |
|
123 |
declare exit handler for SQLEXCEPTION |
|
124 |
begin |
|
125 |
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; |
|
126 |
set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text); |
|
127 |
if error_handler_active() then |
|
128 |
call initError_P(true); |
|
129 |
signal sqlstate '01FWD' set message_text = tmp; |
|
130 |
return null; |
|
131 |
else |
|
132 |
signal sqlstate 'FWD00' set message_text = tmp; |
|
133 |
end if; |
|
134 |
end; |
|
135 |
return totimestring_lti(v, fmt, tz); |
|
136 |
end; |
|
137 |
$$ |
|
138 |
/** |
|
139 |
* Computes a new date by adding respective number of time units. |
|
140 |
* Corresponds to the 4GL ADD-INTERVAL function. |
|
141 |
* |
|
142 |
* @param initial |
|
143 |
* The first date. |
|
144 |
* @param amount |
|
145 |
* The count of units to be added. |
|
146 |
* @param unit |
|
147 |
* The unit to measure the interval. |
|
148 |
* |
|
149 |
* @return The date that is amount units further in time. |
|
150 |
*/ |
|
151 |
create or replace function guarded_addinterval_dit(initial DATE, amount INTEGER, unit TEXT) |
|
152 |
returns date |
|
153 |
deterministic |
|
154 |
begin |
|
155 |
declare tmp text; |
|
156 |
declare exit handler for SQLEXCEPTION |
|
157 |
begin |
|
158 |
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; |
|
159 |
set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text); |
|
160 |
if error_handler_active() then |
|
161 |
call initError_P(true); |
|
162 |
signal sqlstate '01FWD' set message_text = tmp; |
|
163 |
return null; |
|
164 |
else |
|
165 |
signal sqlstate 'FWD00' set message_text = tmp; |
|
166 |
end if; |
|
167 |
end; |
|
168 |
return addinterval_dit(initial, amount, unit); |
|
169 |
end; |
|
170 |
$$ |
|
171 |
/** |
|
172 |
* Computes a new date by adding respective number of time units. |
|
173 |
* Corresponds to the 4GL ADD-INTERVAL function. |
|
174 |
* |
|
175 |
* @param initial |
|
176 |
* The first date. |
|
177 |
* @param amount |
|
178 |
* The count of units to be added. |
|
179 |
* @param unit |
|
180 |
* The unit to measure the interval. |
|
181 |
* |
|
182 |
* @return The date that is amount units further in time. |
|
183 |
*/ |
|
184 |
create or replace function guarded_addinterval_dlt(initial DATE, amount BIGINT, unit TEXT) |
|
185 |
returns date |
|
186 |
deterministic |
|
187 |
begin |
|
188 |
declare tmp text; |
|
189 |
declare exit handler for SQLEXCEPTION |
|
190 |
begin |
|
191 |
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; |
|
192 |
set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text); |
|
193 |
if error_handler_active() then |
|
194 |
call initError_P(true); |
|
195 |
signal sqlstate '01FWD' set message_text = tmp; |
|
196 |
return null; |
|
197 |
else |
|
198 |
signal sqlstate 'FWD00' set message_text = tmp; |
|
199 |
end if; |
|
200 |
end; |
|
201 |
return addinterval_dlt(initial, amount, unit); |
|
202 |
end; |
|
203 |
$$ |
|
204 |
/** |
|
205 |
* Computes a new date by adding respective number of time units. |
|
206 |
* Corresponds to the 4GL ADD-INTERVAL function. |
|
207 |
* |
|
208 |
* @param initial |
|
209 |
* The first date. |
|
210 |
* @param amount |
|
211 |
* The count of units to be added. |
|
212 |
* @param unit |
|
213 |
* The unit to measure the interval. |
|
214 |
* |
|
215 |
* @return The date that is amount units further in time. |
|
216 |
*/ |
|
217 |
create or replace function guarded_addinterval_sit(initial TIMESTAMP(3), amount INTEGER, unit TEXT) |
|
218 |
returns timestamp(3) |
|
219 |
deterministic |
|
220 |
begin |
|
221 |
declare tmp text; |
|
222 |
declare exit handler for SQLEXCEPTION |
|
223 |
begin |
|
224 |
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; |
|
225 |
set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text); |
|
226 |
if error_handler_active() then |
|
227 |
call initError_P(true); |
|
228 |
signal sqlstate '01FWD' set message_text = tmp; |
|
229 |
return null; |
|
230 |
else |
|
231 |
signal sqlstate 'FWD00' set message_text = tmp; |
|
232 |
end if; |
|
233 |
end; |
|
234 |
return addinterval_sit(initial, amount, unit); |
|
235 |
end; |
|
236 |
$$ |
|
237 |
/** |
|
238 |
* Computes a new date by adding respective number of time units. |
|
239 |
* Corresponds to the 4GL ADD-INTERVAL function. |
|
240 |
* |
|
241 |
* @param initial |
|
242 |
* The first date. |
|
243 |
* @param amount |
|
244 |
* The count of units to be added. |
|
245 |
* @param unit |
|
246 |
* The unit to measure the interval. |
|
247 |
* |
|
248 |
* @return The date that is amount units further in time. |
|
249 |
*/ |
|
250 |
create or replace function guarded_addinterval_slt(initial TIMESTAMP(3), amount BIGINT, unit TEXT) |
|
251 |
returns timestamp(3) |
|
252 |
deterministic |
|
253 |
begin |
|
254 |
declare tmp text; |
|
255 |
declare exit handler for SQLEXCEPTION |
|
256 |
begin |
|
257 |
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; |
|
258 |
set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text); |
|
259 |
if error_handler_active() then |
|
260 |
call initError_P(true); |
|
261 |
signal sqlstate '01FWD' set message_text = tmp; |
|
262 |
return null; |
|
263 |
else |
|
264 |
signal sqlstate 'FWD00' set message_text = tmp; |
|
265 |
end if; |
|
266 |
end; |
|
267 |
return addinterval_slt(initial, amount, unit); |
|
268 |
end; |
|
269 |
$$ |
|
270 |
/** |
|
271 |
* Test whether one string begins with another case insensitively. |
|
272 |
* Corresponds to the 4GL BEGINS operator |
|
273 |
*/ |
|
274 |
create or replace function guarded_begins_tt(a TEXT, b TEXT) |
|
275 |
returns boolean |
|
276 |
deterministic |
|
277 |
begin |
|
278 |
declare tmp text; |
|
279 |
declare exit handler for SQLEXCEPTION |
|
280 |
begin |
|
281 |
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; |
|
282 |
set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text); |
|
283 |
if error_handler_active() then |
|
284 |
call initError_P(true); |
|
285 |
signal sqlstate '01FWD' set message_text = tmp; |
|
286 |
return null; |
|
287 |
else |
|
288 |
signal sqlstate 'FWD00' set message_text = tmp; |
|
289 |
end if; |
|
290 |
end; |
|
291 |
return begins_tt(a, b); |
|
292 |
end; |
|
293 |
$$ |
|
294 |
/** |
|
295 |
* Test whether one string begins with another, optionally taking case into account. |
|
296 |
* Corresponds to the 4GL BEGINS operator |
|
297 |
*/ |
|
298 |
create or replace function guarded_begins_ttb(a TEXT, b TEXT, cs BOOLEAN) |
|
299 |
returns boolean |
|
300 |
deterministic |
|
301 |
begin |
|
302 |
declare tmp text; |
|
303 |
declare exit handler for SQLEXCEPTION |
|
304 |
begin |
|
305 |
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; |
|
306 |
set tmp = sformat('ERROR {} ({}): {}', @sqlstate, @errno, @text); |
|
307 |
if error_handler_active() then |
|
308 |
call initError_P(true); |
|
309 |
signal sqlstate '01FWD' set message_text = tmp; |
|
310 |
return null; |
|
311 |
else |
|
312 |
signal sqlstate 'FWD00' set message_text = tmp; |
|
313 |
end if; |
|
314 |
end; |
|
315 |
return begins_ttb(a, b, cs); |
|
316 |
end; |
|
317 |
$$ |
|
318 |
/** |
|
319 |
* Returns the uppercase representation of the string. |
|
320 |
* Corresponds to the 4GL CAPS function |
|
321 |
*/ |
|
322 |
create or replace function guarded_caps_t(t TEXT) |
|
323 |
returns text |
|
324 |
deterministic |