mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-23 05:53:06 +01:00
269 lines
10 KiB
Python
269 lines
10 KiB
Python
#coding:utf-8
|
||
#
|
||
# id: bugs.core_2724
|
||
# title: Validate or transform string of DML queries so that engine internals doesn't receive malformed strings
|
||
# decription:
|
||
# Code from doc/sql.extensions/README.ddl_triggers.txt was taken as basis for this test
|
||
# (see ticket issue: "This situation happened with DDL triggers ...").
|
||
# Several DB objects are created here and their DDL contain unicode (Greek) text.
|
||
# Attachment these issues these DDL intentionally is run with charset = NONE.
|
||
# This charset (NONE) should result in question marks after we finish DDL and want to query log table
|
||
# that was filled by DDL trigger and contains issued DDL statements.
|
||
#
|
||
# tracker_id: CORE-2724
|
||
# min_versions: ['3.0']
|
||
# versions: 3.0
|
||
# qmid: None
|
||
|
||
import pytest
|
||
from firebird.qa import db_factory, isql_act, Action
|
||
|
||
# version: 3.0
|
||
# resources: None
|
||
|
||
substitutions_1 = [('SQL_TEXT .*', 'SQL_TEXT'), ('RESULT_INFO .*', 'RESULT_INFO')]
|
||
|
||
init_script_1 = """
|
||
create sequence ddl_seq;
|
||
|
||
create table ddl_log (
|
||
id bigint not null primary key,
|
||
moment timestamp not null,
|
||
current_connection_cset varchar(31) not null,
|
||
event_type varchar(25) not null,
|
||
object_type varchar(25) not null,
|
||
ddl_event varchar(25) not null,
|
||
object_name varchar(31) not null,
|
||
old_object_name varchar(31),
|
||
new_object_name varchar(31),
|
||
sql_text blob sub_type text not null,
|
||
ok char(1) not null,
|
||
result_info blob sub_type text
|
||
);
|
||
commit;
|
||
|
||
set term ^;
|
||
create trigger trig_ddl_log_before before any ddl statement
|
||
as
|
||
declare id type of column ddl_log.id;
|
||
declare v_current_connection_cset varchar(31);
|
||
begin
|
||
-- We do the changes in an AUTONOMOUS TRANSACTION, so if an exception happens and the command
|
||
-- didn't run, the log will survive.
|
||
in autonomous transaction do
|
||
begin
|
||
|
||
select coalesce(c.rdb$character_set_name, '??? NULL ???')
|
||
from mon$attachments a
|
||
left join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id
|
||
where a.mon$attachment_id = current_connection
|
||
into v_current_connection_cset;
|
||
|
||
insert into ddl_log (id, moment, current_connection_cset,
|
||
event_type, object_type, ddl_event, object_name,
|
||
old_object_name, new_object_name, sql_text, ok, result_info)
|
||
values (next value for ddl_seq,
|
||
'now',
|
||
:v_current_connection_cset,
|
||
rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE'),
|
||
rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE'),
|
||
rdb$get_context('DDL_TRIGGER', 'DDL_EVENT'),
|
||
rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME'),
|
||
rdb$get_context('DDL_TRIGGER', 'OLD_OBJECT_NAME'),
|
||
rdb$get_context('DDL_TRIGGER', 'NEW_OBJECT_NAME'),
|
||
rdb$get_context('DDL_TRIGGER', 'SQL_TEXT'),
|
||
'N',
|
||
'Κάτι συνέβη. Θα πρέπει να ελέγξετε') -- Something was wrong. One need to check this.
|
||
returning id into id;
|
||
rdb$set_context('USER_SESSION', 'trig_ddl_log_id', id);
|
||
end
|
||
end
|
||
^
|
||
|
||
-- Note: the above trigger will fire for this DDL command. It's good idea to use -nodbtriggers
|
||
-- when working with them!
|
||
create trigger trig_ddl_log_after after any ddl statement
|
||
as
|
||
begin
|
||
-- Here we need an AUTONOMOUS TRANSACTION because the original transaction will not see the
|
||
-- record inserted on the BEFORE trigger autonomous transaction if user transaction is not
|
||
-- READ COMMITTED.
|
||
in autonomous transaction do
|
||
update ddl_log set ok = 'Y',
|
||
result_info = 'Τα πάντα ήταν επιτυχής' -- Everything has completed successfully
|
||
where id = rdb$get_context('USER_SESSION', 'trig_ddl_log_id');
|
||
end
|
||
^
|
||
set term ;^
|
||
commit;
|
||
|
||
-- So lets delete the record about trig_ddl_log_after creation.
|
||
delete from ddl_log;
|
||
commit;
|
||
"""
|
||
|
||
db_1 = db_factory(charset='UTF8', sql_dialect=3, init=init_script_1)
|
||
|
||
# test_script_1
|
||
#---
|
||
#
|
||
# import os
|
||
# import time
|
||
# import subprocess
|
||
#
|
||
# os.environ["ISC_USER"] = user_name
|
||
# os.environ["ISC_PASSWORD"] = user_password
|
||
#
|
||
# db_conn.close()
|
||
#
|
||
# #---------------------------------------------
|
||
#
|
||
# def flush_and_close(file_handle):
|
||
# # https://docs.python.org/2/library/os.html#os.fsync
|
||
# # If you're starting with a Python file object f,
|
||
# # first do f.flush(), and
|
||
# # then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk.
|
||
# global os
|
||
#
|
||
# file_handle.flush()
|
||
# if file_handle.mode not in ('r', 'rb'):
|
||
# # otherwise: "OSError: [Errno 9] Bad file descriptor"!
|
||
# os.fsync(file_handle.fileno())
|
||
# file_handle.close()
|
||
#
|
||
# #--------------------------------------------
|
||
#
|
||
# def cleanup( f_names_list ):
|
||
# global os
|
||
# for i in range(len( f_names_list )):
|
||
# if os.path.isfile( f_names_list[i]):
|
||
# os.remove( f_names_list[i] )
|
||
# if os.path.isfile( f_names_list[i]):
|
||
# print('ERROR: can not remove file ' + f_names_list[i])
|
||
#
|
||
# #--------------------------------------------
|
||
#
|
||
#
|
||
# sql_check=''' delete from ddl_log;
|
||
# commit;
|
||
#
|
||
# create domain dm_name varchar(50) check (value in ('αμορτισέρ', 'κόμβο', 'σωλήνα', 'φέροντα', 'βραχίονα'));
|
||
# recreate table t1 (
|
||
# saller_id integer -- αναγνωριστικό εμπόρου // ID of saler
|
||
# ,customer_id integer -- αναγνωριστικό πελάτη // ID of customer
|
||
# ,product_name dm_name
|
||
# );
|
||
# commit;
|
||
# set list on;
|
||
#
|
||
# select id, current_connection_cset, sql_text, result_info, ddl_event, object_name
|
||
# from ddl_log order by id;
|
||
#
|
||
# commit;
|
||
# drop table t1;
|
||
# drop domain dm_name;
|
||
# exit;
|
||
# '''
|
||
#
|
||
# f_check_sql = open( os.path.join(context['temp_directory'],'tmp_check_2724.sql'), 'w')
|
||
# f_check_sql.write(sql_check)
|
||
# flush_and_close( f_check_sql )
|
||
#
|
||
# ##########################################################################################
|
||
#
|
||
# f_ch_none_log = open( os.path.join(context['temp_directory'],'tmp_ch_none_2724.log'), 'w')
|
||
# f_ch_none_err = open( os.path.join(context['temp_directory'],'tmp_ch_none_2724.err'), 'w')
|
||
#
|
||
# subprocess.call( [context['isql_path'], dsn, "-i", f_check_sql.name,
|
||
# "-ch", "none"],
|
||
# stdout = f_ch_none_log,
|
||
# stderr = f_ch_none_err
|
||
# )
|
||
#
|
||
# flush_and_close( f_ch_none_log )
|
||
# flush_and_close( f_ch_none_err )
|
||
#
|
||
# ##########################################################################################
|
||
#
|
||
# f_ch_utf8_log = open( os.path.join(context['temp_directory'],'tmp_ch_utf8_2724.log'), 'w')
|
||
# f_ch_utf8_err = open( os.path.join(context['temp_directory'],'tmp_ch_utf8_2724.err'), 'w')
|
||
#
|
||
# subprocess.call( [context['isql_path'], dsn, "-user", user_name, "-password", user_password, "-i", f_check_sql.name,
|
||
# "-ch", "utf8"],
|
||
# stdout = f_ch_utf8_log,
|
||
# stderr = f_ch_utf8_err
|
||
# )
|
||
# flush_and_close( f_ch_utf8_log )
|
||
# flush_and_close( f_ch_utf8_err )
|
||
#
|
||
#
|
||
# f_list = [f_ch_none_log, f_ch_none_err, f_ch_utf8_log, f_ch_utf8_err]
|
||
# for f in f_list:
|
||
# with open( f.name,'r') as f:
|
||
# print(f.read())
|
||
#
|
||
#
|
||
# # Cleanup
|
||
# #########
|
||
# time.sleep(1)
|
||
#
|
||
# f_list.append(f_check_sql)
|
||
# cleanup( [i.name for i in f_list] )
|
||
#
|
||
#
|
||
#---
|
||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||
|
||
expected_stdout_1 = """
|
||
ID 2
|
||
CURRENT_CONNECTION_CSET NONE
|
||
SQL_TEXT
|
||
create domain dm_name varchar(50) check (value in ('??????????????????', '??????????', '????????????', '??????????????', '????????????????'))
|
||
RESULT_INFO
|
||
Τα πάντα ήταν επιτυχής
|
||
DDL_EVENT CREATE DOMAIN
|
||
OBJECT_NAME DM_NAME
|
||
|
||
ID 3
|
||
CURRENT_CONNECTION_CSET NONE
|
||
SQL_TEXT
|
||
recreate table t1 (
|
||
saller_id integer -- ?????????????????????????? ?????????????? // ID of saler
|
||
,customer_id integer -- ?????????????????????????? ???????????? // ID of customer
|
||
,product_name dm_name
|
||
)
|
||
RESULT_INFO
|
||
Τα πάντα ήταν επιτυχής
|
||
DDL_EVENT CREATE TABLE
|
||
OBJECT_NAME T1
|
||
|
||
ID 6
|
||
CURRENT_CONNECTION_CSET UTF8
|
||
SQL_TEXT 80:0
|
||
create domain dm_name varchar(50) check (value in ('αμορτισέρ', 'κόμβο', 'σωλήνα', 'φέροντα', 'βραχίονα'))
|
||
RESULT_INFO 80:2
|
||
Τα πάντα ήταν επιτυχής
|
||
DDL_EVENT CREATE DOMAIN
|
||
OBJECT_NAME DM_NAME
|
||
|
||
ID 7
|
||
CURRENT_CONNECTION_CSET UTF8
|
||
SQL_TEXT
|
||
recreate table t1 (
|
||
saller_id integer -- αναγνωριστικό εμπόρου // ID of saler
|
||
,customer_id integer -- αναγνωριστικό πελάτη // ID of customer
|
||
,product_name dm_name
|
||
)
|
||
RESULT_INFO
|
||
Τα πάντα ήταν επιτυχής
|
||
DDL_EVENT CREATE TABLE
|
||
OBJECT_NAME T1
|
||
"""
|
||
|
||
@pytest.mark.version('>=3.0')
|
||
@pytest.mark.xfail
|
||
def test_1(db_1):
|
||
pytest.fail("Test not IMPLEMENTED")
|
||
|
||
|