diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 430acb8e..f7906c02 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -19,13 +19,13 @@ jobs:
integration:
needs: unit
runs-on: ubuntu-latest
- timeout-minutes: 5
+ timeout-minutes: 10
env:
HTTP_BIN_HOST: http://localhost:8080
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- - run: docker run -d -p8080:80 kennethreitz/httpbin
+ - run: npm run docker:start
- run: npm install
- run: npm run integration
performance:
diff --git a/abaplint.jsonc b/abaplint.jsonc
index fc2898c3..314c4c82 100644
--- a/abaplint.jsonc
+++ b/abaplint.jsonc
@@ -118,7 +118,7 @@
"inline_data_old_versions": false,
"intf_referencing_clas": false,
"keep_single_parameter_on_one_line": true,
- "line_break_multiple_parameters": false,
+ "line_break_multiple_parameters": true,
"line_break_style": false,
"msag_consistency": true,
"nesting": true,
@@ -182,7 +182,16 @@
"check_ddic": true,
"implement_methods": true,
"indentation": true,
- "keyword_case": true,
+ "keyword_case": {
+ "style": "upper",
+ "ignoreExceptions": false,
+ "ignoreLowerClassImplmentationStatement": false,
+ "ignoreGlobalClassDefinition": false,
+ "ignoreGlobalInterface": false,
+ "ignoreFunctionModuleName": false,
+ "ignoreGlobalClassBoundaries": false,
+ "ignoreKeywords": []
+ },
"when_others_last": true,
"newline_between_methods": true,
"avoid_use": {
diff --git a/package.json b/package.json
index 7813ce2f..a6b475ff 100644
--- a/package.json
+++ b/package.json
@@ -9,14 +9,17 @@
"flame": "0x -o -- node --expose-gc test/performance.mjs",
"performance": "rm -rf output && abap_transpile ./abap_transpile_test.json && node --expose-gc test/performance.mjs",
"integration": "rm -rf output && abap_transpile ./abap_transpile_test.json && node --expose-gc output/index.mjs",
+ "postgres:init": "cat test/adbc/init.sql | docker exec -i postgresql psql -U postgres -d postgres",
+ "docker:start": "docker compose -p open-abap -f test/stack.yml up -d --wait && npm run postgres:init",
"test": "npm run lint && npm run unit"
},
"license": "MIT",
"dependencies": {
- "@abaplint/cli": "^2.113.91",
- "@abaplint/database-sqlite": "^2.10.20",
- "@abaplint/runtime": "^2.10.23",
- "@abaplint/transpiler-cli": "^2.10.23",
+ "@abaplint/cli": "^2.113.99",
+ "@abaplint/database-pg": "^2.10.24",
+ "@abaplint/database-sqlite": "^2.10.24",
+ "@abaplint/runtime": "^2.10.24",
+ "@abaplint/transpiler-cli": "^2.10.24",
"0x": "^5.8.0"
}
}
diff --git a/src/abap/math/cl_abap_random.clas.testclasses.abap b/src/abap/math/cl_abap_random.clas.testclasses.abap
index d22c586a..23361ece 100644
--- a/src/abap/math/cl_abap_random.clas.testclasses.abap
+++ b/src/abap/math/cl_abap_random.clas.testclasses.abap
@@ -21,7 +21,9 @@ CLASS ltcl_test IMPLEMENTATION.
DATA lv_int TYPE i.
lo_random = cl_abap_random=>create( ).
DO 10 TIMES.
- lv_int = lo_random->intinrange( low = 10 high = 20 ).
+ lv_int = lo_random->intinrange(
+ low = 10
+ high = 20 ).
cl_abap_unit_assert=>assert_number_between(
lower = 10
upper = 20
diff --git a/src/adbc/cl_sql_connection.clas.abap b/src/adbc/cl_sql_connection.clas.abap
new file mode 100644
index 00000000..926a19cb
--- /dev/null
+++ b/src/adbc/cl_sql_connection.clas.abap
@@ -0,0 +1,51 @@
+CLASS cl_sql_connection DEFINITION PUBLIC.
+ PUBLIC SECTION.
+ CLASS-METHODS get_connection
+ IMPORTING
+ con_name TYPE clike
+ sharable TYPE abap_bool DEFAULT abap_false
+ RETURNING
+ VALUE(connection) TYPE REF TO cl_sql_connection.
+
+ " added in 7.53
+ CLASS-METHODS get_abap_connection
+ IMPORTING
+ con_name TYPE clike
+ RETURNING
+ VALUE(connection) TYPE REF TO cl_sql_connection.
+
+ METHODS create_statement
+ RETURNING
+ VALUE(statement) TYPE REF TO cl_sql_statement.
+
+ METHODS get_con_name
+ RETURNING
+ VALUE(con_name) TYPE string.
+
+ PRIVATE SECTION.
+ DATA mv_con_name TYPE string.
+ENDCLASS.
+
+CLASS cl_sql_connection IMPLEMENTATION.
+ METHOD get_con_name.
+ con_name = mv_con_name.
+ ENDMETHOD.
+
+ METHOD create_statement.
+ CREATE OBJECT statement EXPORTING con_ref = me.
+ ENDMETHOD.
+
+ METHOD get_connection.
+ " only supported for now,
+ ASSERT sharable = abap_true.
+ CREATE OBJECT connection.
+ connection->mv_con_name = con_name.
+ ENDMETHOD.
+
+ METHOD get_abap_connection.
+ connection = get_connection(
+ con_name = con_name
+ sharable = abap_true ).
+ ENDMETHOD.
+
+ENDCLASS.
\ No newline at end of file
diff --git a/src/adbc/cl_sql_statement.clas.abap b/src/adbc/cl_sql_statement.clas.abap
index 4aab0013..00e8743c 100644
--- a/src/adbc/cl_sql_statement.clas.abap
+++ b/src/adbc/cl_sql_statement.clas.abap
@@ -1,7 +1,8 @@
CLASS cl_sql_statement DEFINITION PUBLIC.
PUBLIC SECTION.
METHODS constructor
- IMPORTING con_ref TYPE REF TO object OPTIONAL.
+ IMPORTING
+ con_ref TYPE REF TO cl_sql_connection OPTIONAL.
METHODS execute_update
IMPORTING
@@ -22,13 +23,21 @@ CLASS cl_sql_statement DEFINITION PUBLIC.
statement TYPE string
RAISING
cx_sql_exception.
+
+ PRIVATE SECTION.
+ DATA mv_connection TYPE string.
ENDCLASS.
CLASS cl_sql_statement IMPLEMENTATION.
METHOD constructor.
-* todo,
- ASSERT con_ref IS INITIAL.
+ IF con_ref IS INITIAL.
+ mv_connection = 'DEFAULT'.
+ ELSE.
+ mv_connection = con_ref->get_con_name( ).
+ ENDIF.
+
+ ASSERT mv_connection IS NOT INITIAL.
ENDMETHOD.
METHOD execute_ddl.
@@ -41,7 +50,7 @@ CLASS cl_sql_statement IMPLEMENTATION.
ASSERT statement IS NOT INITIAL.
- WRITE '@KERNEL if (abap.context.databaseConnections["DEFAULT"] === undefined) {'.
+ WRITE '@KERNEL if (abap.context.databaseConnections[this.mv_connection.get()] === undefined) {'.
lv_sql_message = 'not connected to db'.
WRITE '@KERNEL }'.
IF lv_sql_message IS NOT INITIAL.
@@ -49,7 +58,7 @@ CLASS cl_sql_statement IMPLEMENTATION.
ENDIF.
WRITE '@KERNEL try {'.
- WRITE '@KERNEL await abap.context.databaseConnections["DEFAULT"].execute(statement.get());'.
+ WRITE '@KERNEL await abap.context.databaseConnections[this.mv_connection.get()].execute(statement.get());'.
WRITE '@KERNEL } catch(e) {'.
WRITE '@KERNEL lv_sql_message.set(e + "");'.
WRITE '@KERNEL }'.
@@ -60,29 +69,28 @@ CLASS cl_sql_statement IMPLEMENTATION.
ENDMETHOD.
METHOD execute_query.
+ DATA lx_osql TYPE REF TO cx_sy_dynamic_osql_semantics.
DATA lv_sql_message TYPE string.
ASSERT statement IS NOT INITIAL.
+ ASSERT mv_connection IS NOT INITIAL.
- WRITE '@KERNEL if (abap.context.databaseConnections["DEFAULT"] === undefined) {'.
+ WRITE '@KERNEL if (abap.context.databaseConnections[this.mv_connection.get()] === undefined) {'.
lv_sql_message = 'not connected to db'.
WRITE '@KERNEL }'.
IF lv_sql_message IS NOT INITIAL.
- RAISE EXCEPTION TYPE cx_sql_exception.
+ RAISE EXCEPTION TYPE cx_sql_exception EXPORTING sql_message = lv_sql_message.
ENDIF.
CREATE OBJECT result_set.
- WRITE '@KERNEL try {'.
- WRITE '@KERNEL const res = await abap.context.databaseConnections["DEFAULT"].select({select: statement.get()});'.
+ TRY.
+ WRITE '@KERNEL const res = await abap.context.databaseConnections[this.mv_connection.get()].select({select: statement.get()});'.
* WRITE '@KERNEL console.dir(res.rows);'.
- WRITE '@KERNEL result_set.get().mv_magic = res.rows;'.
- WRITE '@KERNEL } catch(e) {'.
- WRITE '@KERNEL lv_sql_message.set(e + "");'.
- WRITE '@KERNEL }'.
- IF lv_sql_message IS NOT INITIAL.
- RAISE EXCEPTION TYPE cx_sql_exception.
- ENDIF.
+ WRITE '@KERNEL result_set.get().mv_magic = res.rows;'.
+ CATCH cx_sy_dynamic_osql_semantics INTO lx_osql.
+ RAISE EXCEPTION TYPE cx_sql_exception EXPORTING sql_message = lx_osql->sqlmsg.
+ ENDTRY.
ENDMETHOD.
diff --git a/src/adbc/cx_sql_exception.clas.abap b/src/adbc/cx_sql_exception.clas.abap
index 0fbb227a..9af72645 100644
--- a/src/adbc/cx_sql_exception.clas.abap
+++ b/src/adbc/cx_sql_exception.clas.abap
@@ -1,7 +1,21 @@
CLASS cx_sql_exception DEFINITION PUBLIC INHERITING FROM cx_static_check.
+ PUBLIC SECTION.
+ DATA sql_message TYPE string.
+ METHODS constructor
+ IMPORTING
+ textid LIKE textid OPTIONAL
+ sql_message TYPE string OPTIONAL
+ previous TYPE REF TO cx_root OPTIONAL.
ENDCLASS.
CLASS cx_sql_exception IMPLEMENTATION.
+ METHOD constructor.
+ super->constructor(
+ textid = textid
+ previous = previous ).
+
+ me->sql_message = sql_message.
+ ENDMETHOD.
ENDCLASS.
\ No newline at end of file
diff --git a/src/date_time/cl_abap_datfm.clas.testclasses.abap b/src/date_time/cl_abap_datfm.clas.testclasses.abap
index 45143295..051e53ad 100644
--- a/src/date_time/cl_abap_datfm.clas.testclasses.abap
+++ b/src/date_time/cl_abap_datfm.clas.testclasses.abap
@@ -37,8 +37,12 @@ CLASS ltcl_test_datfm IMPLEMENTATION.
ex_datint = date_internal_actual
ex_datfmused = format_used_actual ).
- cl_abap_unit_assert=>assert_equals( exp = christmas act = date_internal_actual ).
- cl_abap_unit_assert=>assert_equals( exp = gregorian_dot_seperated act = format_used_actual ).
+ cl_abap_unit_assert=>assert_equals(
+ exp = christmas
+ act = date_internal_actual ).
+ cl_abap_unit_assert=>assert_equals(
+ exp = gregorian_dot_seperated
+ act = format_used_actual ).
ENDMETHOD.
METHOD acc_conv_ext_to_int_infinity.
@@ -55,8 +59,10 @@ CLASS ltcl_test_datfm IMPLEMENTATION.
ex_datint = date_internal_actual
ex_datfmused = format_used_actual ).
- cl_abap_unit_assert=>assert_equals( exp = infinity act = date_internal_actual ).
- cl_abap_unit_assert=>assert_equals( exp = gregorian_dot_seperated act = format_used_actual ).
+ cl_abap_unit_assert=>assert_equals( exp = infinity
+ act = date_internal_actual ).
+ cl_abap_unit_assert=>assert_equals( exp = gregorian_dot_seperated
+ act = format_used_actual ).
ENDMETHOD.
METHOD acc_conv_ext_to_int_initial.
@@ -73,8 +79,10 @@ CLASS ltcl_test_datfm IMPLEMENTATION.
ex_datint = date_internal_actual
ex_datfmused = format_used_actual ).
- cl_abap_unit_assert=>assert_equals( exp = initial act = date_internal_actual ).
- cl_abap_unit_assert=>assert_equals( exp = gregorian_dot_seperated act = format_used_actual ).
+ cl_abap_unit_assert=>assert_equals( exp = initial
+ act = date_internal_actual ).
+ cl_abap_unit_assert=>assert_equals( exp = gregorian_dot_seperated
+ act = format_used_actual ).
ENDMETHOD.
diff --git a/src/http/cl_http_utility.clas.abap b/src/http/cl_http_utility.clas.abap
index b8522625..66b579df 100644
--- a/src/http/cl_http_utility.clas.abap
+++ b/src/http/cl_http_utility.clas.abap
@@ -111,7 +111,8 @@ CLASS cl_http_utility IMPLEMENTATION.
str = ls_field-name && '=' && ls_field-value.
APPEND str TO tab.
ENDLOOP.
- string = concat_lines_of( table = tab sep = '&' ).
+ string = concat_lines_of( table = tab
+ sep = '&' ).
ENDMETHOD.
METHOD encode_x_base64.
diff --git a/src/ixml/cl_ixml.clas.locals_imp.abap b/src/ixml/cl_ixml.clas.locals_imp.abap
index a4499eb4..b367b92c 100644
--- a/src/ixml/cl_ixml.clas.locals_imp.abap
+++ b/src/ixml/cl_ixml.clas.locals_imp.abap
@@ -410,7 +410,8 @@ CLASS lcl_node IMPLEMENTATION.
li_children = if_ixml_node~get_children( ).
IF mv_name <> '#text' AND ostream->get_pretty_print( ) = abap_true.
- ostream->write_string( repeat( val = | | occ = ostream->get_indent( ) ) ).
+ ostream->write_string( repeat( val = | |
+ occ = ostream->get_indent( ) ) ).
ENDIF.
IF mv_name <> '#text'.
@@ -439,7 +440,8 @@ CLASS lcl_node IMPLEMENTATION.
ostream->write_string( lcl_escape=>escape_value( mv_value ) ).
IF mv_name <> '#text'.
IF ostream->get_pretty_print( ) = abap_true AND has_direct_text( ) = abap_false.
- ostream->write_string( repeat( val = | | occ = ostream->get_indent( ) ) ).
+ ostream->write_string( repeat( val = | |
+ occ = ostream->get_indent( ) ) ).
ENDIF.
ostream->write_string( '' && lv_ns && mv_name && '>' ).
ENDIF.
diff --git a/src/ixml/cl_ixml.clas.testclasses.abap b/src/ixml/cl_ixml.clas.testclasses.abap
index a2c75208..cce9fe42 100644
--- a/src/ixml/cl_ixml.clas.testclasses.abap
+++ b/src/ixml/cl_ixml.clas.testclasses.abap
@@ -481,7 +481,8 @@ CLASS ltcl_xml IMPLEMENTATION.
lv_xml = ||.
li_doc = parse( lv_xml ).
- li_node ?= li_doc->find_from_name_ns( depth = 0 name = 'abapGit' ).
+ li_node ?= li_doc->find_from_name_ns( depth = 0
+ name = 'abapGit' ).
li_version = li_node->get_attributes( )->get_named_item_ns( 'vers' ).
cl_abap_unit_assert=>assert_not_initial( li_version ).
@@ -503,7 +504,8 @@ CLASS ltcl_xml IMPLEMENTATION.
lv_xml = ||.
li_doc = parse( lv_xml ).
- li_element ?= li_doc->find_from_name_ns( depth = 0 name = 'abapGit' ).
+ li_element ?= li_doc->find_from_name_ns( depth = 0
+ name = 'abapGit' ).
cl_abap_unit_assert=>assert_not_initial( li_element ).
cl_abap_unit_assert=>assert_equals(
@@ -523,7 +525,8 @@ CLASS ltcl_xml IMPLEMENTATION.
lv_xml = ||.
li_doc = parse( lv_xml ).
- li_element ?= li_doc->find_from_name_ns( depth = 0 name = 'abapGit' ).
+ li_element ?= li_doc->find_from_name_ns( depth = 0
+ name = 'abapGit' ).
cl_abap_unit_assert=>assert_not_initial( li_element ).
* not found, should return blank
@@ -544,7 +547,8 @@ CLASS ltcl_xml IMPLEMENTATION.
lv_xml = ||.
li_doc = parse( lv_xml ).
- li_element ?= li_doc->find_from_name_ns( depth = 0 name = 'DATA' ).
+ li_element ?= li_doc->find_from_name_ns( depth = 0
+ name = 'DATA' ).
cl_abap_unit_assert=>assert_not_initial( li_element ).
* not found, should return blank
@@ -564,10 +568,12 @@ CLASS ltcl_xml IMPLEMENTATION.
lv_xml = |&<>"'|.
li_doc = parse( lv_xml ).
- li_element ?= li_doc->find_from_name_ns( depth = 0 name = 'moo' ).
+ li_element ?= li_doc->find_from_name_ns( depth = 0
+ name = 'moo' ).
cl_abap_unit_assert=>assert_not_initial( li_element ).
- li_element ?= mi_document->find_from_name_ns( depth = 0 name = 'moo' ).
+ li_element ?= mi_document->find_from_name_ns( depth = 0
+ name = 'moo' ).
cl_abap_unit_assert=>assert_equals(
act = li_element->get_value( )
@@ -585,10 +591,12 @@ CLASS ltcl_xml IMPLEMENTATION.
lv_xml = | A |.
li_doc = parse( lv_xml ).
- li_element ?= li_doc->find_from_name_ns( depth = 0 name = 'moo' ).
+ li_element ?= li_doc->find_from_name_ns( depth = 0
+ name = 'moo' ).
cl_abap_unit_assert=>assert_not_initial( li_element ).
- li_element ?= mi_document->find_from_name_ns( depth = 0 name = 'moo' ).
+ li_element ?= mi_document->find_from_name_ns( depth = 0
+ name = 'moo' ).
" todo
" cl_abap_unit_assert=>assert_equals(
diff --git a/src/json/#ui2#cl_json.clas.abap b/src/json/#ui2#cl_json.clas.abap
index 58b42d30..6432cd2e 100644
--- a/src/json/#ui2#cl_json.clas.abap
+++ b/src/json/#ui2#cl_json.clas.abap
@@ -116,12 +116,14 @@ CLASS /ui2/cl_json IMPLEMENTATION.
ELSEIF data IS INITIAL.
r_json = '""'.
ELSE.
- r_json = '"' && escape( val = |{ data }| format = cl_abap_format=>e_json_string ) && '"'.
+ r_json = '"' && escape( val = |{ data }|
+ format = cl_abap_format=>e_json_string ) && '"'.
ENDIF.
WHEN cl_abap_typedescr=>typekind_xstring.
r_json = '"' && cl_http_utility=>encode_x_base64( data ) && '"'.
WHEN cl_abap_typedescr=>typekind_string.
- r_json = '"' && escape( val = data format = cl_abap_format=>e_json_string ) && '"'.
+ r_json = '"' && escape( val = data
+ format = cl_abap_format=>e_json_string ) && '"'.
WHEN cl_abap_typedescr=>typekind_int.
r_json = |{ data }|.
WHEN cl_abap_typedescr=>typekind_num.
@@ -191,7 +193,9 @@ CLASS /ui2/cl_json IMPLEMENTATION.
r_json = r_json && ','.
ENDLOOP.
IF r_json CP '*,'.
- r_json = substring( val = r_json off = 0 len = strlen( r_json ) - 1 ).
+ r_json = substring( val = r_json
+ off = 0
+ len = strlen( r_json ) - 1 ).
ENDIF.
r_json = r_json && '}'.
WHEN cl_abap_typedescr=>kind_ref.
diff --git a/src/kernel/call_transformation/kernel_call_transformation.clas.locals_imp.abap b/src/kernel/call_transformation/kernel_call_transformation.clas.locals_imp.abap
index 8a25be98..6930e2e7 100644
--- a/src/kernel/call_transformation/kernel_call_transformation.clas.locals_imp.abap
+++ b/src/kernel/call_transformation/kernel_call_transformation.clas.locals_imp.abap
@@ -284,7 +284,8 @@ CLASS lcl_object_to_sxml IMPLEMENTATION.
WRITE '@KERNEL result.assign(INPUT.source[name]);'.
WRITE '@KERNEL }'.
mi_writer->open_element( name = 'str' ).
- mi_writer->write_attribute( name = 'name' value = to_upper( lv_name ) ).
+ mi_writer->write_attribute( name = 'name'
+ value = to_upper( lv_name ) ).
traverse_write( result ).
mi_writer->close_element( ).
WRITE '@KERNEL }'.
@@ -334,7 +335,8 @@ CLASS lcl_object_to_sxml IMPLEMENTATION.
ASSIGN COMPONENT ls_compo-name OF STRUCTURE TO .
GET REFERENCE OF INTO lv_ref.
mi_writer->open_element( name = traverse_write_type( lv_ref ) ).
- mi_writer->write_attribute( name = 'name' value = to_upper( ls_compo-name ) ).
+ mi_writer->write_attribute( name = 'name'
+ value = to_upper( ls_compo-name ) ).
traverse_write( lv_ref ).
mi_writer->close_element( ).
ENDLOOP.
diff --git a/src/sxml/cl_sxml_string_reader.clas.locals_imp.abap b/src/sxml/cl_sxml_string_reader.clas.locals_imp.abap
index ac1b47a9..a7a0b3ff 100644
--- a/src/sxml/cl_sxml_string_reader.clas.locals_imp.abap
+++ b/src/sxml/cl_sxml_string_reader.clas.locals_imp.abap
@@ -89,9 +89,11 @@ CLASS lcl_json_parser IMPLEMENTATION.
CASE lv_type.
WHEN 'object'.
- traverse_object( iv_json = iv_json iv_key = iv_key ).
+ traverse_object( iv_json = iv_json
+ iv_key = iv_key ).
WHEN 'array'.
- traverse_array( iv_json = iv_json iv_key = iv_key ).
+ traverse_array( iv_json = iv_json
+ iv_key = iv_key ).
WHEN 'string' OR 'boolean' OR 'number' OR 'null'.
WRITE '@KERNEL iv_json = iv_json.value + "";'.
diff --git a/src/sxml/cl_sxml_string_writer.clas.testclasses.abap b/src/sxml/cl_sxml_string_writer.clas.testclasses.abap
index 595a0ba8..567b7b7c 100644
--- a/src/sxml/cl_sxml_string_writer.clas.testclasses.abap
+++ b/src/sxml/cl_sxml_string_writer.clas.testclasses.abap
@@ -24,7 +24,8 @@ CLASS ltcl_json IMPLEMENTATION.
intf ?= writer.
intf->open_element( name = 'object' ).
intf->open_element( name = 'str' ).
- intf->write_attribute( name = 'name' value = 'text' ).
+ intf->write_attribute( name = 'name'
+ value = 'text' ).
intf->write_value( 'moo' ).
intf->close_element( ).
intf->close_element( ).
@@ -97,11 +98,13 @@ CLASS ltcl_json IMPLEMENTATION.
intf ?= writer.
intf->open_element( name = 'object' ).
intf->open_element( name = 'str' ).
- intf->write_attribute( name = 'name' value = 'text' ).
+ intf->write_attribute( name = 'name'
+ value = 'text' ).
intf->write_value( 'moo' ).
intf->close_element( ).
intf->open_element( name = 'str' ).
- intf->write_attribute( name = 'name' value = 'next' ).
+ intf->write_attribute( name = 'name'
+ value = 'next' ).
intf->write_value( 'moo' ).
intf->close_element( ).
intf->close_element( ).
diff --git a/src/unit/cl_abap_unit_assert.clas.testclasses.abap b/src/unit/cl_abap_unit_assert.clas.testclasses.abap
index 39b64517..d75c1c3e 100644
--- a/src/unit/cl_abap_unit_assert.clas.testclasses.abap
+++ b/src/unit/cl_abap_unit_assert.clas.testclasses.abap
@@ -118,12 +118,16 @@ CLASS ltcl_test IMPLEMENTATION.
METHOD equals.
DATA bar TYPE i.
- cl_abap_unit_assert=>assert_equals( act = bar exp = bar ).
+ cl_abap_unit_assert=>assert_equals( act = bar
+ exp = bar ).
bar = 2.
- cl_abap_unit_assert=>assert_equals( act = bar exp = bar ).
+ cl_abap_unit_assert=>assert_equals( act = bar
+ exp = bar ).
- cl_abap_unit_assert=>assert_equals( act = 2 exp = 2 ).
- cl_abap_unit_assert=>assert_equals( act = 'hello' exp = 'hello' ).
+ cl_abap_unit_assert=>assert_equals( act = 2
+ exp = 2 ).
+ cl_abap_unit_assert=>assert_equals( act = 'hello'
+ exp = 'hello' ).
ENDMETHOD.
METHOD equals_date.
diff --git a/test/adbc/init.sql b/test/adbc/init.sql
new file mode 100644
index 00000000..b79a5f0b
--- /dev/null
+++ b/test/adbc/init.sql
@@ -0,0 +1,9 @@
+CREATE TABLE films (
+ code char(5),
+ title varchar(40),
+ did integer,
+ date_prod date,
+ kind varchar(10),
+ len interval hour to minute,
+ CONSTRAINT code_title PRIMARY KEY(code,title)
+);
\ No newline at end of file
diff --git a/test/adbc/zcl_adbc_test.clas.abap b/test/adbc/zcl_adbc_test.clas.abap
new file mode 100644
index 00000000..5fa67593
--- /dev/null
+++ b/test/adbc/zcl_adbc_test.clas.abap
@@ -0,0 +1,7 @@
+CLASS zcl_adbc_test DEFINITION PUBLIC.
+ PUBLIC SECTION.
+ENDCLASS.
+
+CLASS zcl_adbc_test IMPLEMENTATION.
+
+ENDCLASS.
\ No newline at end of file
diff --git a/test/adbc/zcl_adbc_test.clas.testclasses.abap b/test/adbc/zcl_adbc_test.clas.testclasses.abap
new file mode 100644
index 00000000..bd29af79
--- /dev/null
+++ b/test/adbc/zcl_adbc_test.clas.testclasses.abap
@@ -0,0 +1,22 @@
+CLASS ltcl_test DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION MEDIUM FINAL.
+
+ PRIVATE SECTION.
+ METHODS test FOR TESTING RAISING cx_static_check.
+
+ENDCLASS.
+
+CLASS ltcl_test IMPLEMENTATION.
+ METHOD test.
+
+ DATA lo_stmt TYPE REF TO cl_sql_statement.
+ DATA lv_sql TYPE string.
+ DATA lo_result TYPE REF TO cl_sql_result_set.
+
+
+ lo_stmt = cl_sql_connection=>get_abap_connection( 'PG' )->create_statement( ).
+
+ lv_sql = |select * from films|.
+ lo_result = lo_stmt->execute_query( lv_sql ).
+
+ ENDMETHOD.
+ENDCLASS.
\ No newline at end of file
diff --git a/test/cl_http_client.clas.testclasses.abap b/test/cl_http_client.clas.testclasses.abap
index 2d4f7470..d22bbaf0 100644
--- a/test/cl_http_client.clas.testclasses.abap
+++ b/test/cl_http_client.clas.testclasses.abap
@@ -136,7 +136,8 @@ CLASS ltcl_test IMPLEMENTATION.
IMPORTING
client = li_client ).
- li_client->authenticate( username = 'sdf' password = 'sdf' ).
+ li_client->authenticate( username = 'sdf'
+ password = 'sdf' ).
li_client->send( ).
li_client->receive( ).
@@ -177,11 +178,13 @@ CLASS ltcl_test IMPLEMENTATION.
ASSERT li_client->request->get_method( ) = ''.
ASSERT li_client->request->get_header_field( 'sdfds' ) = ''.
- li_client->authenticate( username = 'sdf' password = 'sdf' ).
+ li_client->authenticate( username = 'sdf'
+ password = 'sdf' ).
ASSERT li_client->request->get_header_field( 'Authorization' ) = 'Basic c2RmOnNkZg=='.
ASSERT li_client->request->get_header_field( 'authorizaTION' ) = 'Basic c2RmOnNkZg=='.
- li_client->request->set_header_field( name = 'FOObar' value = '42' ).
+ li_client->request->set_header_field( name = 'FOObar'
+ value = '42' ).
li_client->request->get_header_fields( CHANGING fields = fields ).
ASSERT lines( fields ) = 3.
@@ -223,7 +226,8 @@ CLASS ltcl_test IMPLEMENTATION.
ssl_id = 'ANONYM'
IMPORTING
client = li_client ).
- li_client->request->set_form_field( name = 'foo' value = 'bar' ).
+ li_client->request->set_form_field( name = 'foo'
+ value = 'bar' ).
li_client->send( ).
li_client->receive( ).
@@ -357,7 +361,8 @@ CLASS ltcl_test IMPLEMENTATION.
ssl_id = 'ANONYM'
IMPORTING
client = li_client ).
- li_client->request->set_header_field( name = '~request_uri' value = lv_uri ).
+ li_client->request->set_header_field( name = '~request_uri'
+ value = lv_uri ).
lv_val = li_client->request->get_header_field( name = '~request_uri' ).
cl_abap_unit_assert=>assert_equals(
act = lv_uri
@@ -398,8 +403,10 @@ CLASS ltcl_test IMPLEMENTATION.
IMPORTING
client = li_client ).
li_client->request->set_method( 'POST' ).
- li_client->request->set_form_field( name = 'foo1' value = 'bar1' ).
- li_client->request->set_form_field( name = 'foo2' value = 'bar2' ).
+ li_client->request->set_form_field( name = 'foo1'
+ value = 'bar1' ).
+ li_client->request->set_form_field( name = 'foo2'
+ value = 'bar2' ).
li_client->request->set_content_type( 'application/x-www-form-urlencoded' ).
li_client->send( ).
diff --git a/test/setup.mjs b/test/setup.mjs
index e87b65f4..336d9efc 100644
--- a/test/setup.mjs
+++ b/test/setup.mjs
@@ -1,8 +1,19 @@
import {SQLiteDatabaseClient} from "@abaplint/database-sqlite";
+import {PostgresDatabaseClient} from "@abaplint/database-pg";
export async function setup(abap, schemas, insert) {
abap.context.databaseConnections["DEFAULT"] = new SQLiteDatabaseClient();
await abap.context.databaseConnections["DEFAULT"].connect();
await abap.context.databaseConnections["DEFAULT"].execute(schemas.sqlite);
await abap.context.databaseConnections["DEFAULT"].execute(insert);
+
+ abap.context.databaseConnections["PG"] = new PostgresDatabaseClient({
+ user: "postgres",
+ host: "localhost",
+ database: "postgres",
+ password: "postgres",
+ port: 5432,
+// trace: true,
+ lazy: true,
+ });
}
\ No newline at end of file
diff --git a/test/stack.yml b/test/stack.yml
new file mode 100644
index 00000000..6b89fcb0
--- /dev/null
+++ b/test/stack.yml
@@ -0,0 +1,21 @@
+services:
+ postgresql:
+ image: postgres:17
+ container_name: postgresql
+ restart: always
+ environment:
+ POSTGRES_PASSWORD: postgres
+ ports:
+ - '5432:5432'
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
+ interval: 1s
+ timeout: 20s
+ retries: 5
+ tmpfs:
+ - /var/lib/postgresql/data
+ httpbin:
+ image: kennethreitz/httpbin
+ container_name: httpbin
+ ports:
+ - '8080:80'
\ No newline at end of file