diff --git a/.circleci/config.yml b/.circleci/config.yml index 435f588d3db..cf0d5b75e91 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -50,8 +50,8 @@ jobs: build: <<: *defaults environment: - MAKEFLAGS: -j 10 - resource_class: large + MAKEFLAGS: -j 8 + resource_class: xlarge steps: - checkout - run: @@ -149,4 +149,6 @@ workflows: requires: - build - - build-windows + - build-windows: + requires: + - build diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ea260ec4c05..939832b8eca 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -23,7 +23,7 @@ /src/broker/ @kisoo-han /src/cm_common/ @kisoo-han /src/compat/ @beyondykk9 -/src/jsp/ @beyondykk9 +/src/sp/ @beyondykk9 /src/method/ @beyondykk9 /src/optimizer/ @shparkcubrid /src/parser/ @beyondykk9 @@ -51,3 +51,4 @@ /src/thread @beyondykk9 /src/loaddb @kisoo-han +/pl_engine @beyondykk9 diff --git a/contrib/msg/de_DE.utf8/cubrid.msg b/contrib/msg/de_DE.utf8/cubrid.msg index 0262ec64705..c137fc259b7 100644 --- a/contrib/msg/de_DE.utf8/cubrid.msg +++ b/contrib/msg/de_DE.utf8/cubrid.msg @@ -1445,8 +1445,9 @@ $ LOADDB 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 Letzter Fehler +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 Letzter Fehler $set 6 MSGCAT_SET_INTERNAL 1 Fehler in Fehler-Subsystem (Zeile %1$d): @@ -1937,7 +1938,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 Außer virtuellem Speicher: %1$d Bytes können nicht zugewiesen werden. diff --git a/contrib/msg/de_DE.utf8/utils.msg b/contrib/msg/de_DE.utf8/utils.msg index 9bbe93bc475..22858916223 100644 --- a/contrib/msg/de_DE.utf8/utils.msg +++ b/contrib/msg/de_DE.utf8/utils.msg @@ -157,7 +157,7 @@ Vorhandene Serviceutilities:\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ Vorhandene Administratorutilities:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ Vorhandene Befehle:\n\ 42 Parameter ist Ungültig.\n 43 Datei(%1$s) offene Fehler.\n 44 Cubrid Utility, Version %1$s\n\ -Anwendung: %2$s javasp [args]\n\ +Anwendung: %2$s pl [args]\n\ \n\ Vorhandene Befehle:\n\ - start [database-name]\n\ - stop [database-name]\n\ restart [database-name]\n\ status [database-name]\n 45 cubrid utility, version %1$s\n\ diff --git a/contrib/msg/es_ES.utf8/cubrid.msg b/contrib/msg/es_ES.utf8/cubrid.msg index 753aa31a42b..e6dbc954a88 100644 --- a/contrib/msg/es_ES.utf8/cubrid.msg +++ b/contrib/msg/es_ES.utf8/cubrid.msg @@ -1445,8 +1445,9 @@ Verifique la ruta del archivo de claves (_keys) y asegúrese de que incluya la c 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 Ultimo error +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 Ultimo error $set 6 MSGCAT_SET_INTERNAL 1 Error en subsistema de error (linea %1$d): @@ -1937,7 +1938,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 Sin memoria virtual: incapaz de asignar %1$d bytes. diff --git a/contrib/msg/es_ES.utf8/utils.msg b/contrib/msg/es_ES.utf8/utils.msg index c7f80c04cc0..bced20a445a 100644 --- a/contrib/msg/es_ES.utf8/utils.msg +++ b/contrib/msg/es_ES.utf8/utils.msg @@ -157,7 +157,7 @@ Utilidades de servicio disponible:\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ Utilidades de administrador disponible:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ Comando disponible: \n\ 42 Argumento invalido.\n 43 Error al abrir archivo (%1$s).\n 44 utilidad de cubrid, version %1$s\n\ -uso: %2$s javasp [args]\n\ +uso: %2$s pl [args]\n\ \n\ Comando disponible:\n\ - start [database-name]\n\ - stop [database-name]\n\ restart [database-name]\n\ status [database-name]\n 45 cubrid utility, version %1$s\n\ diff --git a/contrib/msg/fr_FR.utf8/cubrid.msg b/contrib/msg/fr_FR.utf8/cubrid.msg index 7729f06c276..bbe0e738c28 100644 --- a/contrib/msg/fr_FR.utf8/cubrid.msg +++ b/contrib/msg/fr_FR.utf8/cubrid.msg @@ -1445,8 +1445,9 @@ Vérifiez le chemin du fichier de clé (_keys) et assurez-vous qu'il inclut la c 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 Dernière erreur +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 Dernière erreur $set 6 MSGCAT_SET_INTERNAL 1 Erreur dans le sous-système d'erreur (ligne %1$d): @@ -1937,7 +1938,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 Mémoire virtuelle épuisée: impossible d'allouer %1$d octets. diff --git a/contrib/msg/fr_FR.utf8/utils.msg b/contrib/msg/fr_FR.utf8/utils.msg index 51da8d51813..97696d8624e 100644 --- a/contrib/msg/fr_FR.utf8/utils.msg +++ b/contrib/msg/fr_FR.utf8/utils.msg @@ -157,7 +157,7 @@ Utilitaires de service disponibles\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ Utilitaires d'administrateur disponibles:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ Commandes disponibles:\n\ 42 Argument invalide.\n 43 Erreur d'ouverture du fichier(%1$s).\n 44 utilitaire CUBRID, version %1$s\n\ -usage: %2$s javasp [args]\n\ +usage: %2$s pl [args]\n\ \n\ Commandes disponibles:\n\ - start [database-name]\n\ - stop [database-name]\n\ restart [database-name]\n\ status [database-name]\n 45 cubrid utility, version %1$s\n\ diff --git a/contrib/msg/it_IT.utf8/cubrid.msg b/contrib/msg/it_IT.utf8/cubrid.msg index db528edf19a..96f1bfe793b 100644 --- a/contrib/msg/it_IT.utf8/cubrid.msg +++ b/contrib/msg/it_IT.utf8/cubrid.msg @@ -1445,8 +1445,9 @@ Controllare il percorso del file della chiave (_keys) e assicurarsi che includa 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 Ultimo errore +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 Ultimo errore $set 6 MSGCAT_SET_INTERNAL 1 Errore nel sottosistema di errore (linea %1$d): @@ -1937,7 +1938,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 Fuori di memoria virtuale: Impossibile allocare %1$d byte. diff --git a/contrib/msg/it_IT.utf8/utils.msg b/contrib/msg/it_IT.utf8/utils.msg index 19f1af94c05..9753fdd2339 100644 --- a/contrib/msg/it_IT.utf8/utils.msg +++ b/contrib/msg/it_IT.utf8/utils.msg @@ -157,7 +157,7 @@ Servizi disponibili:\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ Utilità amministrazione disponibili:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ Commandi disponibili:\n\ 42 Argomento non valido.\n 43 Errore di apertura file(%1$s).\n 44 utilità cubrid, versione %1$s\n\ -uso: %2$s javasp [args]\n\ +uso: %2$s pl [args]\n\ \n\ Commandi disponibili:\n\ - start [database-name]\n\ - stop [database-name]\n\ restart [database-name]\n\ status [database-name]\n 45 cubrid utility, version %1$s\n\ diff --git a/contrib/msg/ja_JP.utf8/cubrid.msg b/contrib/msg/ja_JP.utf8/cubrid.msg index 7d8a0ddc431..f11473cf276 100644 --- a/contrib/msg/ja_JP.utf8/cubrid.msg +++ b/contrib/msg/ja_JP.utf8/cubrid.msg @@ -1445,8 +1445,9 @@ $ LOADDB 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 ラストエラー +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 ラストエラー $set 6 MSGCAT_SET_INTERNAL 1 エラーサブシステムにエラー発生(ライン %1$d): @@ -1937,7 +1938,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 バチャールメモリーが足りません。: %1$dバイトがアロケーションできません。 diff --git a/contrib/msg/ja_JP.utf8/utils.msg b/contrib/msg/ja_JP.utf8/utils.msg index bcaac83211c..d0dc0f37397 100644 --- a/contrib/msg/ja_JP.utf8/utils.msg +++ b/contrib/msg/ja_JP.utf8/utils.msg @@ -157,7 +157,7 @@ cubrid 管理者ユーティリティー、バージョン %1$s\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ 正しい管理者ユーティリティー名:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ cubrid 管理者ユーティリティー、バージョン %1$s\n\ 42 無効なパラメーターです。\n 43 ファイル「%1$s」のオープンに失敗しました。\n 44 cubridユーティリティー、バージョン %1$s\n\ -使い方: %2$s javasp <コマンド> [パラメーター]\n\ +使い方: %2$s pl <コマンド> [パラメーター]\n\ \n\ 正しいコマンド:\n\ - start [データベース名]\n\ - stop [データベース名]\n\ restart [データベース名]\n\ status [データベース名]\n 45 cubridユーティリティー、バージョン %1$s\n\ diff --git a/contrib/msg/km_KH.utf8/cubrid.msg b/contrib/msg/km_KH.utf8/cubrid.msg index 6abf7e0698e..525ea7cd9c2 100644 --- a/contrib/msg/km_KH.utf8/cubrid.msg +++ b/contrib/msg/km_KH.utf8/cubrid.msg @@ -1445,8 +1445,9 @@ Check the path of the key file (_keys) and make sure that it includes proper key 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 Last Error +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 Last Error $set 6 MSGCAT_SET_INTERNAL 1 Error in error subsystem (line %1$d): @@ -1937,7 +1938,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 Out of virtual memory: unable to allocate %1$d bytes. diff --git a/contrib/msg/km_KH.utf8/utils.msg b/contrib/msg/km_KH.utf8/utils.msg index 53fbe8b6333..e100d59e0b3 100644 --- a/contrib/msg/km_KH.utf8/utils.msg +++ b/contrib/msg/km_KH.utf8/utils.msg @@ -157,7 +157,7 @@ Available service's utilities:\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ Available administrator's utilities:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ Available command:\n\ 42 Invalid argument.\n 43 File(%1$s) open error.\n 44 cubrid utility, version %1$s\n\ -usage: %2$s javasp [args]\n\ +usage: %2$s pl [args]\n\ \n\ Available command:\n\ - start [database-name]\n\ - stop [database-name]\n\ restart [database-name]\n\ status [database-name]\n 45 cubrid utility, version %1$s\n\ diff --git a/contrib/msg/ro_RO.utf8/cubrid.msg b/contrib/msg/ro_RO.utf8/cubrid.msg index 81391a4ce77..d6452c44162 100644 --- a/contrib/msg/ro_RO.utf8/cubrid.msg +++ b/contrib/msg/ro_RO.utf8/cubrid.msg @@ -1445,8 +1445,9 @@ Verificați calea fișierului cheie (_keys) și asigurați-vă că acesta includ 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 Ultima eroare +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 Ultima eroare $set 6 MSGCAT_SET_INTERNAL 1 Eroare în subsistemul de erori (linia %1$d): @@ -1937,7 +1938,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 Memorie virtuală epuizată: nu s-au putut aloca %1$d bytes. diff --git a/contrib/msg/ro_RO.utf8/utils.msg b/contrib/msg/ro_RO.utf8/utils.msg index 40e423bc4a3..cb6f231559b 100644 --- a/contrib/msg/ro_RO.utf8/utils.msg +++ b/contrib/msg/ro_RO.utf8/utils.msg @@ -157,7 +157,7 @@ Utilitare de serviciu disponibile:\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ Utilitare de administrare disponibile:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ Comenzi disponibile:\n\ 42 Argument invalid.\n 43 Eroare la deschiderea fişierului(%1$s).\n 44 utilitar CUBRID, versiunea %1$s\n\ -utilizare: %2$s javasp [args]\n\ +utilizare: %2$s pl [args]\n\ \n\ Comenzi disponibile:\n\ - start [database-name]\n\ - stop [database-name]\n\ restart [database-name]\n\ status [database-name]\n 45 cubrid utility, version %1$s\n\ diff --git a/contrib/msg/tr_TR.utf8/cubrid.msg b/contrib/msg/tr_TR.utf8/cubrid.msg index 0fa6891ae59..2c87c6619bb 100644 --- a/contrib/msg/tr_TR.utf8/cubrid.msg +++ b/contrib/msg/tr_TR.utf8/cubrid.msg @@ -1445,8 +1445,9 @@ Anahtar dosyasının (_keys) yolunu kontrol edin ve uygun anahtarı içerdiğind 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 Son Hata +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 Son Hata $set 6 MSGCAT_SET_INTERNAL 1 Alt Hata içinde hata (satır %1$d): @@ -1937,7 +1938,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 Sanal bellek yetersiz: %1$d bayt bölüm ayıramadı. diff --git a/contrib/msg/tr_TR.utf8/utils.msg b/contrib/msg/tr_TR.utf8/utils.msg index ec9f0a279dd..04fb5aa0588 100644 --- a/contrib/msg/tr_TR.utf8/utils.msg +++ b/contrib/msg/tr_TR.utf8/utils.msg @@ -157,7 +157,7 @@ Mevcut hizmetin programları:\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ Mevcut yönetici programları:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ Mevcut komut:\n\ 42 Değişken geçersiz.\n 43 (%1$s) dosya açma hatası.\n 44 cubrid yardımcı programı, sürüm %1$s\n\ -kullanım: %2$s javasp [args]\n\ +kullanım: %2$s pl [args]\n\ \n\ Mevcut komut:\n\ - start [database-name]\n\ - stop [database-name]\n\ restart [database-name]\n\ status [database-name]\n 45 cubrid utility, version %1$s\n\ diff --git a/contrib/msg/vi_VN.utf8/cubrid.msg b/contrib/msg/vi_VN.utf8/cubrid.msg index 96ebb1c07a1..eac8d471668 100644 --- a/contrib/msg/vi_VN.utf8/cubrid.msg +++ b/contrib/msg/vi_VN.utf8/cubrid.msg @@ -1452,8 +1452,9 @@ Check the path of the key file (_keys) and make sure that it includes proper key 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 Last Error +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 Last Error $set 6 MSGCAT_SET_INTERNAL 1 Error in error subsystem (line %1$d): @@ -1944,7 +1945,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 Out of virtual memory: unable to allocate %1$d bytes. diff --git a/contrib/msg/vi_VN.utf8/utils.msg b/contrib/msg/vi_VN.utf8/utils.msg index 8ce230523fa..0b80a308296 100644 --- a/contrib/msg/vi_VN.utf8/utils.msg +++ b/contrib/msg/vi_VN.utf8/utils.msg @@ -157,7 +157,7 @@ Available service's utilities:\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ Available administrator's utilities:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ Available command:\n\ 42 Invalid argument.\n 43 File(%1$s) open error.\n 44 cubrid utility, version %1$s\n\ -usage: %2$s javasp [args]\n\ +usage: %2$s pl [args]\n\ \n\ Available command:\n\ - start [database-name]\n\ - stop [database-name]\n\ restart [database-name]\n\ status [database-name]\n 45 cubrid utility, version %1$s\n\ diff --git a/contrib/msg/zh_CN.utf8/cubrid.msg b/contrib/msg/zh_CN.utf8/cubrid.msg index b6bc389bb9f..953d0dbcc99 100644 --- a/contrib/msg/zh_CN.utf8/cubrid.msg +++ b/contrib/msg/zh_CN.utf8/cubrid.msg @@ -1446,8 +1446,9 @@ $ LOADDB 1359 Java VM crashed: %1$s 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s - -1361 最后一个错误. +1361 Dropping system generated stored procedure is not allowed. +1362 PL/CSQL Stored procedure/function does not support Invoker's rights +1363 最后一个错误. $set 6 MSGCAT_SET_INTERNAL 1 在错误子系统中错误 (line %1$d): @@ -1938,7 +1939,10 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 Unsupported return type '%1$s' of the stored procedure 321 %TYPE type specification is allowed only for PL/CSQL 322 Table column '%1$s.%2$s' has not been defined -323 Stored procedure/function '%1$s' has OUT or IN OUT arguments +323 Stored procedure/function "%1$s" does not exist. +324 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +325 Only trailing default parameter is allowed: invalid at '%1$s'. +326 Stored procedure/function '%1$s' has OUT or IN OUT arguments $set 9 MSGCAT_SET_PARSER_RUNTIME 1 虚拟内存耗尽: 无法申请 %1$d 字节. diff --git a/contrib/msg/zh_CN.utf8/utils.msg b/contrib/msg/zh_CN.utf8/utils.msg index 9f2af417d31..2d92f513a3f 100644 --- a/contrib/msg/zh_CN.utf8/utils.msg +++ b/contrib/msg/zh_CN.utf8/utils.msg @@ -157,7 +157,7 @@ cubrid 管理工具,版本 %1$s\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ 可用的管理员工具:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ cubrid 管理工具,版本 %1$s\n\ 42 无效的参数.\n 43 打开文件 (%1$s) 时出错.\n 44 cubrid 应用工具, 版本 %1$s\n\ -用法: %2$s javasp <命令> [参数]\n\ +用法: %2$s pl <命令> [参数]\n\ \n\ 可用命令:\n\ - start [数据库名]\n\ - stop [数据库名]\n\ restart [数据库名]\n\ status [数据库名]\n 45 cubrid 应用工具, 版本 %1$s\n\ diff --git a/contrib/scripts/check_reserved.sql b/contrib/scripts/check_reserved.sql index 11efc3dda8b..f70a477d12c 100644 --- a/contrib/scripts/check_reserved.sql +++ b/contrib/scripts/check_reserved.sql @@ -31,7 +31,7 @@ UNION ALL SELECT 'stored_proc', sp_name, '', '' FROM _db_stored_procedure WHERE sp_name IN :reserved UNION ALL -SELECT 'stored_proc_arg', arg_name, '', sp_name +SELECT 'stored_proc_arg', arg_name, '', sp_of.sp_name FROM _db_stored_procedure_args WHERE arg_name IN :reserved UNION ALL SELECT 'user', name, '', '' diff --git a/cs/CMakeLists.txt b/cs/CMakeLists.txt index 91b4336eebf..65fef46f6ec 100644 --- a/cs/CMakeLists.txt +++ b/cs/CMakeLists.txt @@ -122,6 +122,7 @@ set(BASE_SOURCES ${BASE_DIR}/pinning.cpp ${BASE_DIR}/porting.c ${BASE_DIR}/printer.cpp + ${BASE_DIR}/process_util.c ${BASE_DIR}/release_string.c ${BASE_DIR}/resource_tracker.cpp ${BASE_DIR}/sha1.c @@ -187,6 +188,7 @@ set(CONNECTION_SOURCES set(COMMUNICATION_SOURCES ${COMMUNICATION_DIR}/network_common.cpp + ${COMMUNICATION_DIR}/network_callback_cl.cpp ${COMMUNICATION_DIR}/network_interface_cl.c ${COMMUNICATION_DIR}/network_cl.c ${COMMUNICATION_DIR}/network_histogram.cpp @@ -306,16 +308,15 @@ set(OBJECT_HEADERS ) set(SP_SOURCES - ${SP_DIR}/jsp_cl.c - ${SP_DIR}/jsp_comm.c - ${SP_DIR}/jsp_file.c + ${SP_DIR}/jsp_cl.cpp + ${SP_DIR}/pl_signature.cpp + ${SP_DIR}/pl_comm.c + ${SP_DIR}/pl_struct_compile.cpp + ${SP_DIR}/sp_catalog.cpp ) set(METHOD_SOURCES - ${METHOD_DIR}/method_connection_cl.cpp - ${METHOD_DIR}/method_compile_def.cpp ${METHOD_DIR}/method_callback.cpp - ${METHOD_DIR}/method_def.cpp ${METHOD_DIR}/method_error.cpp ${METHOD_DIR}/method_oid_handler.cpp ${METHOD_DIR}/method_query_handler.cpp @@ -554,14 +555,14 @@ if(WIN32) target_link_libraries(cubridcs LINK_PRIVATE ws2_32) set_target_properties(cubridcs PROPERTIES LINK_FLAGS "/DEF:\"${CMAKE_SOURCE_DIR}/win/cubridcs/cubridcs.def\"" LINK_FLAGS_RELEASE "/NODEFAULTLIB:libcmt.lib" LINK_FLAGS_DEBUG "/NODEFAULTLIB:msvcrt.lib") endif(WIN32) -target_include_directories(cubridcs PRIVATE ${FLEX_INCLUDE_DIRS} ${EP_INCLUDES}) +target_include_directories(cubridcs PRIVATE ${FLEX_INCLUDE_DIRS} ${JAVA_INC} ${EP_INCLUDES}) if(UNIX) target_link_libraries(cubridcs LINK_PRIVATE -Wl,-whole-archive ${EP_LIBS} -Wl,-no-whole-archive) target_link_libraries(cubridcs PUBLIC stdc++fs) target_link_libraries(cubridcs LINK_PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) target_link_libraries(cubridcs LINK_PUBLIC rt) else(UNIX) - target_link_libraries(cubridcs LINK_PRIVATE ${EP_LIBS}) + target_link_libraries(cubridcs LINK_PRIVATE ${EP_LIBS} ${JVM_LIBS}) endif(UNIX) # for dblink target_link_libraries(cubridcs PUBLIC cascci) diff --git a/cubrid/CMakeLists.txt b/cubrid/CMakeLists.txt index 9d1b8f8b215..08b185d1c89 100644 --- a/cubrid/CMakeLists.txt +++ b/cubrid/CMakeLists.txt @@ -196,6 +196,7 @@ set(CONNECTION_SOURCES set(COMMUNICATION_SOURCES ${COMMUNICATION_DIR}/network_common.cpp + ${COMMUNICATION_DIR}/network_callback_sr.cpp ${COMMUNICATION_DIR}/network_interface_sr.c ${COMMUNICATION_DIR}/network_sr.c ) @@ -280,23 +281,30 @@ set(OBJECT_HEADERS ) set(SP_SOURCES - ${SP_DIR}/jsp_comm.c - ${SP_DIR}/jsp_file.c - ${SP_DIR}/jsp_sr.c - ) + ${SP_DIR}/method_invoke_group.cpp + ${SP_DIR}/pl_connection.cpp + ${SP_DIR}/pl_compile_handler.cpp + ${SP_DIR}/pl_execution_stack_context.cpp + ${SP_DIR}/pl_executor.cpp + ${SP_DIR}/pl_query_cursor.cpp + ${SP_DIR}/pl_session.cpp + ${SP_DIR}/pl_signature.cpp + ${SP_DIR}/pl_comm.c + ${SP_DIR}/pl_file.c + ${SP_DIR}/pl_sr.cpp + ${SP_DIR}/pl_sr_jvm.cpp + ${SP_DIR}/sp_code.cpp + ) + +set(SP_HEADERS + ${SP_DIR}/pl_connection.hpp + ${SP_DIR}/pl_execution_stack_context.hpp + ${SP_DIR}/pl_signature.hpp + ${SP_DIR}/pl_struct_compile.cpp +) set(METHOD_SOURCES - ${METHOD_DIR}/method_connection_java.cpp - ${METHOD_DIR}/method_connection_sr.cpp - ${METHOD_DIR}/method_connection_pool.cpp - ${METHOD_DIR}/method_compile_def.cpp - ${METHOD_DIR}/method_compile.cpp - ${METHOD_DIR}/method_def.cpp ${METHOD_DIR}/method_error.cpp - ${METHOD_DIR}/method_invoke_builtin.cpp - ${METHOD_DIR}/method_invoke_group.cpp - ${METHOD_DIR}/method_invoke_java.cpp - ${METHOD_DIR}/method_query_cursor.cpp ${METHOD_DIR}/method_query_util.cpp ${METHOD_DIR}/method_struct_invoke.cpp ${METHOD_DIR}/method_struct_value.cpp @@ -305,7 +313,6 @@ set(METHOD_SOURCES ${METHOD_DIR}/method_struct_schema_info.cpp ${METHOD_DIR}/method_struct_parameter_info.cpp ${METHOD_DIR}/method_scan.cpp - ${METHOD_DIR}/method_runtime_context.cpp ${METHOD_DIR}/query_method.cpp ) @@ -528,6 +535,7 @@ set (CUBRID_LIB_HEADERS ${OBJECT_HEADERS} ${QUERY_HEADERS} ${STORAGE_HEADERS} + ${SP_HEADERS} ${THREAD_HEADERS} ${TRANSACTION_HEADERS} ${XASL_HEADERS} diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 9dbd42e6314..a01ae376f44 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -21,11 +21,6 @@ install(FILES ${CMAKE_SOURCE_DIR}/demo/demodb_schema DESTINATION ${CUBRID_DEMODIR}) -install(DIRECTORY - ${CMAKE_SOURCE_DIR}/demo/plcsql - DESTINATION ${CUBRID_DEMODIR} -) - if(UNIX) set(DEMODB_SCRIPT make_cubrid_demo.sh) else(UNIX) diff --git a/demo/plcsql/README.md b/demo/plcsql/README.md deleted file mode 100644 index f903993bdab..00000000000 --- a/demo/plcsql/README.md +++ /dev/null @@ -1,478 +0,0 @@ -# PLCSQL Demonstaration - -## Table of Contents - -1. [DBMS_OUTPUT](##-1.-DBMS_OUTPUT.put_line) -2. [Static SQL](##-2.-Static-SQL) -3. [TCL](##-3.-TCL-(COMMIT/ROLLBACK)) -4. [Procedure/Function](##-4.-Procedure/Function) -5. [%TYPE](##-5.-%TYPE) -6. [Pseudocolumn](##-6.-Pseudocolumn) ---- -## 1. DBMS_OUTPUT.put_line -- [demo_hello.sql](./demo_hello.sql) -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/demo_hello.sql -``` - -``` --- test -csql -u public demodb -;server-output on - call demo_hello (); -;ex -``` - -``` --- expected -Hello CUBRID PL/CSQL! -``` ---- -## 2. Static SQL -### 2.1 Query - Single Rows -- [test_query_single_row_const.sql](./test_query_single_row_const.sql) -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/test_query_single_row_const.sql -``` - -``` --- test -csql -u public demodb -;server-output on - select test_query_single_row_const (); -;ex -``` -``` --- expected - test_query_single_row_const() -=============================== - 10615 -``` - -- [test_query_single_row.sql](./test_query_single_row.sql) -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/test_query_single_row.sql -``` - -``` --- sample -11847 'Kim Yong-Bae' -11844 'Kim Taek Soo' -11843 'Kim Tae-Gyun' -11842 'Kim Soo-Kyung' -11836 'Kim Moon-Soo' -11833 'Kim Min-Soo' -11830 'Kim Kyung-Seok' -11829 'Kim Kyong-Hun' -11828 'Kim Ki-Tai' -11827 'Kim Jung-Chul' -11825 'Kim Jong-Shin' -11823 'Kim In-Sub' -11820 'Kim Han-Soo' -``` -``` --- test -csql -u public demodb -;server-output on - select test_query_single_row (11828); -;ex -``` -``` --- expected - test_query_single_row(11828) -====================== - 'Kim Ki-Tai' -``` -### 2.2 Query - Cursor -- [test_query_cursor_simple_nocond.sql](./test_query_cursor_simple_nocond.sql) -- [test_query_cursor_simple.sql](./test_query_cursor_simple.sql) -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/test_query_cursor_simple_nocond.sql -csql -u public demodb -i $CUBRID/demo/plcsql/test_query_cursor_simple.sql -``` - -``` --- test -csql -u public demodb -;server-output on - select test_query_cursor_simple_nocond (); - select test_query_cursor_simple (); -;ex -``` -``` --- expected - test_query_cursor_simple_nocond() -=================================== - 10999 - - test_query_cursor_simple() -============================ - 10615 -``` - -- [test_query_cursor_hostvar.sql](./test_query_cursor_hostvar.sql) -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/test_query_cursor_hostvar.sql -``` - -``` --- test -csql -u public demodb -;server-output on - select test_query_cursor_hostvar (); -;ex -``` -``` --- expected - test_query_cursor_hostvar() -====================== - 'Han Myung-Woo' -``` -### 2.3 DDL (Dynamic SQL), DML - -#### Dynmaic SQL -- [test_ddl.sql](./test_ddl.sql) -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/test_ddl.sql -``` - -``` --- test -csql -u public demodb -;server-output on - call test_ddl (); - desc a_tbl1; -;ex -``` -``` --- expected -creating a_tbl1 table is succeed! - - Field Type Null Key Default Extra -==================================================================================================================================== - 'id' 'INTEGER' 'YES' 'UNI' NULL '' - 'name' 'VARCHAR(1073741823)' 'YES' '' NULL '' - 'phone' 'VARCHAR(1073741823)' 'YES' '' '000-0000' '' -``` - -#### INSERT -- [test_dml_insert.sql](./test_dml_insert.sql) -- [test_dml_truncate.sql](./test_dml_truncate.sql) -``` --- preparation and registration -csql -u public demodb - drop table if exists a_tbl1; - CREATE TABLE a_tbl1(id INT UNIQUE, name VARCHAR, phone VARCHAR DEFAULT '000-0000'); -;ex - -csql -u public demodb -i $CUBRID/demo/plcsql/test_dml_insert.sql -csql -u public demodb -i $CUBRID/demo/plcsql/test_dml_truncate.sql -``` - -``` --- test -csql -u public demodb -;server-output on - call test_dml_insert (); -;ex -``` - -``` --- expected -/* (((((( */INSERT INTO a_tbl1 SET id=6, name='eee';/* (((((( */ -/* (((((( */INSERT INTO a_tbl1 SET id=6, name='eee';/* (((((( */ is succeed -[Test 1] ===================================================================== -Expected: -6 eee 666-6666 -Actual: -6 eee 666-6666 -[Test 1] OK -[Test 2] ===================================================================== -Expected: -7 ggg 777-7777 -Actual: -7 ggg 777-7777 -[Test 2] OK -``` - -#### TRUNCATE -``` --- test -csql -u public demodb -;server-output on - call test_dml_truncate (); - SELECT * FROM a_tbl1; -;ex -``` - -``` --- expected -There are no results. -``` - -#### DELETE -- [test_dml_delete.sql](./test_dml_delete.sql) -``` --- preparation -csql -u public demodb - DROP TABLE a_tbl; - CREATE TABLE a_tbl( - id INT NOT NULL, - phone VARCHAR(10)); - INSERT INTO a_tbl VALUES(1,'111-1111'), (2,'222-2222'), (3, '333-3333'), (4, NULL), (5, NULL); -;ex -``` -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/test_dml_delete.sql -``` - -``` --- test -csql -u public demodb -;server-output on - call test_dml_delete (); -;ex -``` -``` --- expected -111-1111 -222-2222 -333-3333 -``` - -## 3. TCL (COMMIT/ROLLBACK) - -### COMMIT -- [test_tcl_commit.sql](./test_tcl_commit.sql) -``` --- preparation -csql -u public demodb - DROP TABLE IF EXISTS test_tcl_tbl; - CREATE TABLE test_tcl_tbl (code INT, name STRING); -;ex -``` -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/test_tcl_commit.sql -``` - -``` --- test (;set pl_transaction_control=yes) -csql -u public demodb -;set pl_transaction_control=yes -;autocommit off -;server-output on - TRUNCATE test_tcl_tbl; - COMMIT; - SELECT * FROM test_tcl_tbl; - CALL test_tcl_commit (); - ROLLBACK; -- rollback in csql session - - SELECT * FROM test_tcl_tbl; -- committed rows should be displayed - ROLLBACK; -;ex -``` -``` --- expected - -// CALL test_tcl_commit (); -code = 3, name = ccc -code = 4, name = ddd - -// SELECT * FROM test_tcl_tbl; - code name -=================================== - 1 'aaa' - 2 'bbb' - 3 'ccc' - 4 'ddd' -``` - -``` --- test (;set pl_transaction_control=no) -csql -u public demodb -;set pl_transaction_control=no -;autocommit off -;server-output on - TRUNCATE test_tcl_tbl; - COMMIT; -- COMMIT is required to ensure TRUNCATE is executed according to the TRUNCATE spec. - - SELECT * FROM test_tcl_tbl; - CALL test_tcl_commit (); - ROLLBACK; -- rollback in csql session - SELECT * FROM test_tcl_tbl; -- COMMIT in test_tcl_commit () must be ignored - ROLLBACK; -;ex -``` - -``` --- expected - -// CALL test_tcl_commit (); -code = 3, name = ccc -code = 4, name = ddd - -// SELECT * FROM test_tcl_tbl; -There are no results. -``` - -### ROLLBACK -- [test_tcl_rollback.sql](./test_tcl_rollback.sql) -``` --- preparation -csql -u public demodb - DROP TABLE IF EXISTS test_tcl_tbl2; - CREATE TABLE test_tcl_tbl2 (code INT, name STRING); -;ex -``` -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/test_tcl_rollback.sql -``` - -``` --- test (;set pl_transaction_control=yes) -csql -u public demodb -;set pl_transaction_control=yes -;set autocommit off -;server-output on - TRUNCATE test_tcl_tbl2; - COMMIT; - CALL test_tcl_rollback (); - COMMIT; - SELECT * FROM test_tcl_tbl2; -;ex -``` - -``` --- expected - code name -=================================== - 1 'aaa' - 2 'bbb' - 3 'ccc' - 4 'ddd' -``` - -``` --- test (;set pl_transaction_control=no) -csql -u public demodb -;set pl_transaction_control=no -;set autocommit off -;server-output on - TRUNCATE test_tcl_tbl2; - COMMIT; - CALL test_tcl_rollback (); - COMMIT; - SELECT * FROM test_tcl_tbl2; -;ex -``` - -``` --- expected - code name -=================================== - 1 'aaa' - 2 'bbb' - 3 'ccc' - 4 'ddd' - 6 'daf' - 7 'qwe' -``` - ---- -## 4. Procedure/Function -- [demo_hello_ret.sql](./demo_hello_ret.sql) -- [demo_global_semantics_udpf.sql](./demo_global_semantics_udpf.sql) -``` --- registration -csql -u public demodb -i $CUBRID/demo/plcsql/demo_hello_ret.sql -csql -u public demodb -i $CUBRID/demo/plcsql/demo_global_semantics_udpf.sql -``` - -``` --- test -csql -u public demodb -;server-output on - select demo_global_semantics_udpf (); -;ex -``` - -``` --- expected - demo_global_semantics_udpf() -====================== - 'hello cubrid' - -Hello CUBRID PL/CSQL! -``` ---- -## 5. %TYPE -- [demo_global_semantics_type.sql](./demo_global_semantics_type.sql) --- registration -``` -csql -u public demodb -i $CUBRID/demo/plcsql/demo_global_semantics_type.sql -``` - -``` --- test -csql -u public demodb -;server-output on - select demo_global_semantics_type (); -;ex -``` -``` --- expected - demo_global_semantics_type() -====================== - 'Chung Min-Tae' -``` ---- -## 6. Pseudocolumn - -### 6.1 Serial -- [demo_global_semantics_serial.sql](./demo_global_semantics_serial.sql) -``` --- preparation -csql -u public demodb - DROP SERIAL demo_pl_serial; - CREATE SERIAL demo_pl_serial; -;ex -``` - --- registration -``` -csql -u public demodb -i $CUBRID/demo/plcsql/demo_global_semantics_serial.sql -``` - -``` --- test -csql -u public demodb -;server-output on - select demo_global_semantics_serial (); - select demo_global_semantics_serial (); - select demo_global_semantics_serial (); -;ex -``` - -``` --- expected - demo_global_semantics_serial() -====================== - 1 - - demo_global_semantics_serial() -====================== - 2 - - demo_global_semantics_serial() -====================== - 3 -``` diff --git a/demo/plcsql/StmtForStaticSqlLoop-test-without-condition.sql b/demo/plcsql/StmtForStaticSqlLoop-test-without-condition.sql deleted file mode 100644 index 31d44c652fa..00000000000 --- a/demo/plcsql/StmtForStaticSqlLoop-test-without-condition.sql +++ /dev/null @@ -1,11 +0,0 @@ -create or replace function StmtForStaticSqlLoop_test_without_condition() return int as -i int; -begin - i := 0; - for r in (select code, name from athlete) loop - i := r.code; - EXIT; - end loop; - - return i; -end; diff --git a/demo/plcsql/demo_global_semantics_serial.sql b/demo/plcsql/demo_global_semantics_serial.sql deleted file mode 100644 index e9d074c592c..00000000000 --- a/demo/plcsql/demo_global_semantics_serial.sql +++ /dev/null @@ -1,6 +0,0 @@ -create or replace function demo_global_semantics_serial() return numeric as -i numeric; -begin - i := demo_pl_serial.NEXT_VALUE; - return i; -end; \ No newline at end of file diff --git a/demo/plcsql/demo_global_semantics_type.sql b/demo/plcsql/demo_global_semantics_type.sql deleted file mode 100644 index 328cfa71687..00000000000 --- a/demo/plcsql/demo_global_semantics_type.sql +++ /dev/null @@ -1,12 +0,0 @@ -create or replace function demo_global_semantics_type() return string as -v_name athlete.name%TYPE; -g char(1) := 'M'; -n char(3) := 'KOR'; - -begin - for r in (select name from athlete where gender = g and nation_code = n) loop - v_name := r.name; - EXIT; - end loop; - return v_name; -end; \ No newline at end of file diff --git a/demo/plcsql/demo_global_semantics_udpf.sql b/demo/plcsql/demo_global_semantics_udpf.sql deleted file mode 100644 index f25fecaaf1f..00000000000 --- a/demo/plcsql/demo_global_semantics_udpf.sql +++ /dev/null @@ -1,7 +0,0 @@ -create or replace function demo_global_semantics_udpf() return varchar as -m varchar; -begin - demo_hello (); - m := demo_hello_ret (); - return m; -end; \ No newline at end of file diff --git a/demo/plcsql/demo_hello.sql b/demo/plcsql/demo_hello.sql deleted file mode 100644 index d9db0445e52..00000000000 --- a/demo/plcsql/demo_hello.sql +++ /dev/null @@ -1,4 +0,0 @@ -create or replace procedure demo_hello() as -begin - DBMS_OUTPUT.put_line('Hello CUBRID PL/CSQL!'); -end; diff --git a/demo/plcsql/demo_hello_ret.sql b/demo/plcsql/demo_hello_ret.sql deleted file mode 100644 index 0581d99eeae..00000000000 --- a/demo/plcsql/demo_hello_ret.sql +++ /dev/null @@ -1,4 +0,0 @@ -create or replace function demo_hello_ret() return varchar as -begin - return 'hello cubrid'; -end; diff --git a/demo/plcsql/test_ddl.sql b/demo/plcsql/test_ddl.sql deleted file mode 100644 index 6022a519d05..00000000000 --- a/demo/plcsql/test_ddl.sql +++ /dev/null @@ -1,11 +0,0 @@ -create or replace procedure test_ddl() as - i int; - n varchar; - p varchar; - - new_table VARCHAR := 'a_tbl1'; -begin - EXECUTE IMMEDIATE 'drop table if exists ' || new_table; - EXECUTE IMMEDIATE 'CREATE TABLE ' || new_table || ' (id INT UNIQUE, name VARCHAR, phone VARCHAR DEFAULT ''000-0000'');'; - DBMS_OUTPUT.put_line ('creating ' || new_table || ' table is succeed!'); -end; diff --git a/demo/plcsql/test_dml_delete.sql b/demo/plcsql/test_dml_delete.sql deleted file mode 100644 index 0a0be734afd..00000000000 --- a/demo/plcsql/test_dml_delete.sql +++ /dev/null @@ -1,27 +0,0 @@ -/* https://www.cubrid.org/manual/en/11.2/sql/query/update.html */ -/* -DROP TABLE a_tbl; -CREATE TABLE a_tbl( - id INT NOT NULL, - phone VARCHAR(10)); -INSERT INTO a_tbl VALUES(1,'111-1111'), (2,'222-2222'), (3, '333-3333'), (4, NULL), (5, NULL); -*/ -create or replace procedure test_dml_delete() as - p varchar; -begin - DELETE FROM a_tbl WHERE phone IS NULL; - -/* - id phone -=================================== - 1 '111-1111' - 2 '222-2222' - 3 '333-3333' - 5 NULL -*/ - - for r in (SELECT phone FROM a_tbl) loop - p := r.phone; - DBMS_OUTPUT.PUT_LINE(p); - end loop; -end; diff --git a/demo/plcsql/test_dml_insert.sql b/demo/plcsql/test_dml_insert.sql deleted file mode 100644 index cc94cefaf17..00000000000 --- a/demo/plcsql/test_dml_insert.sql +++ /dev/null @@ -1,77 +0,0 @@ -/* https://www.cubrid.org/manual/en/11.2/sql/query/insert.html */ -/* - drop table if exists a_tbl1; - CREATE TABLE a_tbl1(id INT UNIQUE, name VARCHAR, phone VARCHAR DEFAULT '000-0000'); -*/ -create or replace procedure test_dml_insert() as - i int; - n varchar; - p varchar; - - new_table VARCHAR := 'a_tbl1'; - temp VARCHAR := ''; -begin --- 0) ---insert default values with DEFAULT keyword before VALUES - INSERT INTO a_tbl1 DEFAULT VALUES; - ---insert multiple rows - INSERT INTO a_tbl1 VALUES (1,'aaa', DEFAULT),(2,'bbb', DEFAULT); - ---insert a single row specifying column values for all - INSERT INTO a_tbl1 VALUES (3,'ccc', '333-3333'); - ---insert two rows specifying column values for only - INSERT INTO a_tbl1(id) VALUES (4), (5); - ---insert a single row with SET clauses - - temp := temp || '/* (('; - temp := temp || '(((( */'; - - temp := temp || 'INSERT INTO a_tbl1 SET id=6, name=''eee'';'; - - temp := temp || '/* (('; - temp := temp || '(((( */'; - - DBMS_OUTPUT.put_line (temp); - - EXECUTE IMMEDIATE temp; - DBMS_OUTPUT.put_line(temp || ' is succeed'); - - INSERT INTO a_tbl1 SET id=7, phone='777-7777'; - --- 1) - DBMS_OUTPUT.PUT_LINE('[Test 1] ====================================================================='); - INSERT INTO a_tbl1 SET id=6, phone='000-0000' ON DUPLICATE KEY UPDATE phone='666-6666'; - --- 2) - DBMS_OUTPUT.PUT_LINE('Expected: '); - DBMS_OUTPUT.PUT_LINE(6 || ' ' || 'eee' || ' ' || '666-6666'); - - DBMS_OUTPUT.PUT_LINE('Actual: '); - for r in (SELECT id, name, phone FROM a_tbl1 WHERE id=6) loop - i := r.id; - n := r.name; - p := r.phone; - DBMS_OUTPUT.PUT_LINE(i || ' ' || n || ' ' || p); - end loop; - DBMS_OUTPUT.PUT_LINE('[Test 1] OK'); - --- 3) - DBMS_OUTPUT.PUT_LINE('[Test 2] ====================================================================='); - DBMS_OUTPUT.PUT_LINE('Expected: '); - DBMS_OUTPUT.PUT_LINE(7 || ' ' || 'ggg' || ' ' || '777-7777'); - - INSERT INTO a_tbl1 SELECT * FROM a_tbl1 WHERE id=7 ON DUPLICATE KEY UPDATE name='ggg'; - - DBMS_OUTPUT.PUT_LINE('Actual: '); - for r in (SELECT id, name, phone FROM a_tbl1 WHERE id=7) loop - i := r.id; - n := r.name; - p := r.phone; - DBMS_OUTPUT.PUT_LINE(i || ' ' || n || ' ' || p); - end loop; - - DBMS_OUTPUT.PUT_LINE('[Test 2] OK'); -end; diff --git a/demo/plcsql/test_dml_truncate.sql b/demo/plcsql/test_dml_truncate.sql deleted file mode 100644 index c15666cc59e..00000000000 --- a/demo/plcsql/test_dml_truncate.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* https://www.cubrid.org/manual/en/11.2/sql/query/truncate.html */ -/* - -*/ -create or replace procedure test_dml_truncate() as -begin - truncate TABLE a_tbl1; -end; diff --git a/demo/plcsql/test_query_cursor_hostvar.sql b/demo/plcsql/test_query_cursor_hostvar.sql deleted file mode 100644 index c87a288df2a..00000000000 --- a/demo/plcsql/test_query_cursor_hostvar.sql +++ /dev/null @@ -1,22 +0,0 @@ -create or replace function test_query_cursor_hostvar() return varchar as - g char(1) := 'M'; - n char(3) := 'KOR'; - - i int; - m varchar; -begin - i := 0; - for r in (select code, name from athlete where gender = g and nation_code = n) loop - i := r.code; - m := r.name; - end loop; - - return m; -exception -when no_data_found then - return 'no_data'; -when too_many_rows then - return 'too_many'; -when others then - return 'others'; -end; diff --git a/demo/plcsql/test_query_cursor_simple.sql b/demo/plcsql/test_query_cursor_simple.sql deleted file mode 100644 index 75c86dc67e8..00000000000 --- a/demo/plcsql/test_query_cursor_simple.sql +++ /dev/null @@ -1,11 +0,0 @@ -create or replace function test_query_cursor_simple() return int as -i int; -begin - i := 0; - for r in (select code, name from athlete where gender = 'M' and nation_code = 'KOR') loop - i := r.code; - EXIT; - end loop; - - return i; -end; diff --git a/demo/plcsql/test_query_cursor_simple_nocond.sql b/demo/plcsql/test_query_cursor_simple_nocond.sql deleted file mode 100644 index 3f0ca2a8b3d..00000000000 --- a/demo/plcsql/test_query_cursor_simple_nocond.sql +++ /dev/null @@ -1,11 +0,0 @@ -create or replace function test_query_cursor_simple_nocond() return int as -i int; -begin - i := 0; - for r in (select code, name from athlete) loop - i := r.code; - EXIT; - end loop; - - return i; -end; \ No newline at end of file diff --git a/demo/plcsql/test_query_single_row.sql b/demo/plcsql/test_query_single_row.sql deleted file mode 100644 index fa20469f932..00000000000 --- a/demo/plcsql/test_query_single_row.sql +++ /dev/null @@ -1,16 +0,0 @@ -create or replace function test_query_single_row(c int) return string as - g char(1) := 'M'; - n char(3) := 'KOR'; - - m varchar; -begin - select name into m from athlete where gender = g and nation_code = n and code = c; - return m; -exception -when no_data_found then - return 'no_data_found'; -when too_many_rows then - return 'too_many_rows'; -when others then - return 'others'; -end; diff --git a/demo/plcsql/test_query_single_row_const.sql b/demo/plcsql/test_query_single_row_const.sql deleted file mode 100644 index 02c8fe4c59b..00000000000 --- a/demo/plcsql/test_query_single_row_const.sql +++ /dev/null @@ -1,14 +0,0 @@ -create or replace function test_query_single_row_const() return int as - c int; - m varchar; -begin - select code, name INTO c, m from athlete where gender = 'M' and nation_code = 'KOR' LIMIT 1; - return c; -exception -when no_data_found then - return 0; -when too_many_rows then - return 100; -when others then - return -1; -end; diff --git a/demo/plcsql/test_semantic_error_unknown_tbl.sql b/demo/plcsql/test_semantic_error_unknown_tbl.sql deleted file mode 100644 index 942665b2f8f..00000000000 --- a/demo/plcsql/test_semantic_error_unknown_tbl.sql +++ /dev/null @@ -1,4 +0,0 @@ -create or replace procedure test_semantic_error_unknown_tbl() as -begin - insert into unknown_tbl(t) values (time'12:13:14'); -end; diff --git a/demo/plcsql/test_semantic_error_wrong_literal.sql b/demo/plcsql/test_semantic_error_wrong_literal.sql deleted file mode 100644 index 1577716389a..00000000000 --- a/demo/plcsql/test_semantic_error_wrong_literal.sql +++ /dev/null @@ -1,7 +0,0 @@ -/* - create table test_insert(t time); -*/ -create or replace procedure test_wrong_literal() as -begin - insert into test_insert(t) values (time'12:13:14.123'); -- wrong time literal -end; diff --git a/demo/plcsql/test_tcl_commit.sql b/demo/plcsql/test_tcl_commit.sql deleted file mode 100644 index 5b5dca1fa68..00000000000 --- a/demo/plcsql/test_tcl_commit.sql +++ /dev/null @@ -1,30 +0,0 @@ -/* -csql -u public demodb -DROP TABLE IF EXISTS test_tcl_tbl; -CREATE TABLE test_tcl_tbl (code INT, name STRING); - -csql -u public demodb -;autocommit off -;server-output on -TRUNCATE test_tcl_tbl; -CALL test_tcl_commit (); -ROLLBACK; -- rollback in csql session -SELECT * FROM test_tcl_tbl; -- committed rows should be displayed -*/ -create or replace procedure test_tcl_commit() as - i int; - n varchar; -begin - INSERT INTO test_tcl_tbl VALUES (1,'aaa'); - INSERT INTO test_tcl_tbl VALUES (2,'bbb'); - INSERT INTO test_tcl_tbl VALUES (3,'ccc'); - INSERT INTO test_tcl_tbl VALUES (4,'ddd'); - COMMIT; - - for r in (SELECT code, name FROM test_tcl_tbl WHERE code > 2) loop - i := r.code; - n := r.name; - DBMS_OUTPUT.PUT_LINE(i); - DBMS_OUTPUT.PUT_LINE('code = ' || i || ' name = ' || n); - end loop; -end; diff --git a/demo/plcsql/test_tcl_rollback.sql b/demo/plcsql/test_tcl_rollback.sql deleted file mode 100644 index 64304b7a9b0..00000000000 --- a/demo/plcsql/test_tcl_rollback.sql +++ /dev/null @@ -1,45 +0,0 @@ -/* -=====[PREAPRE SCHEMA]======================================= -DROP TABLE IF EXISTS test_tcl_tbl2; -CREATE TABLE test_tcl_tbl2 (code INT, name STRING); - -=====[TEST]================================================= -;set autocommit off -;server-output on - -TRUNCATE test_tcl_tbl2; -CALL test_tcl_rollback (); -COMMIT; -SELECT * FROM test_tcl_tbl2; - -=====[Expected]============================================= - Expected: - === === - - code name - =================================== - 1 'aaa' - 2 'bbb' - 3 'ccc' - 4 'ddd' -*/ -create or replace procedure test_tcl_rollback () as - i int; - n varchar; -begin - INSERT INTO test_tcl_tbl2 VALUES (1,'aaa'); - INSERT INTO test_tcl_tbl2 VALUES (2,'bbb'); - INSERT INTO test_tcl_tbl2 VALUES (3,'ccc'); - INSERT INTO test_tcl_tbl2 VALUES (4,'ddd'); - COMMIT; - - INSERT INTO test_tcl_tbl2 VALUES (6,'daf'); - INSERT INTO test_tcl_tbl2 VALUES (7,'qwe'); - ROLLBACK; - - for r in (SELECT code, name FROM test_tcl_tbl2 WHERE code > 2) loop - i := r.code; - n := r.name; - DBMS_OUTPUT.PUT_LINE('code = ' || i || ', name = ' || n); - end loop; -end; diff --git a/msg/en_US.utf8/cubrid.msg b/msg/en_US.utf8/cubrid.msg index 01f06b7c7ec..e16e6cb6819 100644 --- a/msg/en_US.utf8/cubrid.msg +++ b/msg/en_US.utf8/cubrid.msg @@ -215,12 +215,12 @@ $set 5 MSGCAT_SET_ERROR 143 Encountered a class with no owner. 144 Unable to access user object. 145 Cannot issue grant/revoke commands to yourself. -146 Cannot issue GRANT/REVOKE to owner of a class. +146 Cannot issue GRANT/REVOKE to owner of a %1$s. 147 No GRANT option. 148 Cannot obtain write lock on authorization object. 149 Cannot create instance of authorization object. 150 Cannot revoke privileges from self. -151 Cannot revoke privileges from owner of a class. +151 Cannot revoke privileges from owner of a %1$s. 152 GRANT not found. 153 No authorization privileges in effect for the database. 154 Incomplete authorization installation - no authorization privileges in effect for the database. @@ -236,7 +236,7 @@ $set 5 MSGCAT_SET_ERROR 164 User "%1$s" already exists. 165 User "%1$s" is invalid. 166 Invalid user specified. -167 DBA, members of DBA group and class owner can perform the operation. +167 DBA, members of DBA group and %1$s owner can perform the operation. 168 Member not found. 169 Cannot remove user %1$s from the database. 170 No user logged in. @@ -1452,8 +1452,12 @@ Check the path of the key file (_keys) and make sure that it includes proper key 1361 Invalid result cache for subquery. 1362 Locale '%1$s' is unavailable. +1363 Dropping system generated stored procedure is not allowed. +1364 PL/CSQL Stored procedure/function does not support Invoker's rights. -1363 Last Error +1365 Only DBA and the owner can grant the %1$s privilege. + +1366 Last Error $set 6 MSGCAT_SET_INTERNAL 1 Error in error subsystem (line %1$d): @@ -1949,6 +1953,14 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 324 '%1$s' is not a record variable. 325 The argument specifying the language must be a string literal. +325 The argument specifying the language must be a string literal. +326 Stored procedure/function "%1$s" does not exist. +327 Attempting to assign DEFAULT on an Out parameter is not allowed: '%1$s'. +328 Only trailing default parameter is allowed: invalid at '%1$s'. +329 Grant option is not allowed for %1$s. + + + $set 9 MSGCAT_SET_PARSER_RUNTIME 1 Out of virtual memory: unable to allocate %1$d bytes. 2 Transaction isolation level must be 4, 5 or 6. @@ -2232,3 +2244,11 @@ including those from the current backup level and higher.\n 28 The time(%1$s) specified must be after the time(%2$s) of the specified backup.\n 29 COMMENT: Log archive %1$s, which contains log pages before %2$lld, is not needed any longer by any HA utilities.\n 30 Number of active log archives has been exceeded the max desired number. + +$set 17 MSGCAT_SET_GLOSSARY +1 class +2 trigger +3 serial +4 server +5 synonym +6 procedure diff --git a/msg/en_US.utf8/utils.msg b/msg/en_US.utf8/utils.msg index 182cb53ac57..83bb00bb9fa 100644 --- a/msg/en_US.utf8/utils.msg +++ b/msg/en_US.utf8/utils.msg @@ -157,7 +157,7 @@ Available service's utilities:\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ Available administrator's utilities:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ Available command:\n\ 42 Invalid argument.\n 43 File(%1$s) open error.\n 44 cubrid utility, version %1$s\n\ -usage: %2$s javasp [args]\n\ +usage: %2$s pl [args]\n\ \n\ Available command:\n\ - start [database-name]\n\ - stop [database-name]\n\ restart [database-name]\n\ status [database-name]\n 45 cubrid utility, version %1$s\n\ diff --git a/msg/ko_KR.utf8/cubrid.msg b/msg/ko_KR.utf8/cubrid.msg index cfa1ec39fef..e07f91be2e2 100644 --- a/msg/ko_KR.utf8/cubrid.msg +++ b/msg/ko_KR.utf8/cubrid.msg @@ -215,12 +215,12 @@ $set 5 MSGCAT_SET_ERROR 143 소유자가 없는 클래스가 발생하였습니다. 144 사용자 오브젝트를 액세스할 수 없습니다. 145 자기 자신에 대해 GRANT/REVOKE 명령할 수 없습니다. -146 클래스 소유자에 대해 GRANT/REVOKE 명령할 수 없습니다. +146 %1$s 소유자에 대해 GRANT/REVOKE 명령할 수 없습니다. 147 GRANT 옵션이 없습니다. 148 권한 부여 오브젝트에 대해 쓰기 락을 얻을 수 없습니다. 149 권한 부여 오브젝트의 인스턴스를 생성할 수 없습니다. 150 자기 자신의 권한은 해제할 수 없습니다. -151 클래스 소유자의 권한은 해제할 수 없습니다. +151 %1$s 소유자의 권한은 해제할 수 없습니다. 152 GRANT가 없습니다. 153 데이터베이스에 대한 권한 부여 권리가 없습니다. 154 불완전한 권한 부여 설정 - 데이터베이스에 대한 권한 부여 권리가 없습니다. @@ -236,7 +236,7 @@ $set 5 MSGCAT_SET_ERROR 164 사용자 "%1$s" 이(가) 이미 존재합니다. 165 사용자 "%1$s" 을(를) 확인하십시오. 166 유효하지 않은 사용자가 지정되었습니다. -167 클래스 소유자만이 오퍼레이션을 수행할 수 있습니다. +167 %1$s 소유자만이 오퍼레이션을 수행할 수 있습니다. 168 멤버를 찾을 수 없습니다. 169 데이터베이스에서 사용자를 제거할 수 없습니다. 170 로그인된 사용자가 없습니다. @@ -1450,10 +1450,13 @@ $ LOADDB 1360 In line %1$d, column %2$d\nStored procedure compile error: %3$s 1361 부질의 캐시가 잘못되었습니다. - 1362 언어 '%1$s'에 대한 로캘은 사용 가능하지 않습니다. +1363 시스템 생성 stored procedure를 삭제(drop)할 수 없습니다. +1364 PL/CSQL 저장 프로시저/함수는 호출자 권한을 지원하지 않습니다. + +1365 DBA 및 소유자만 %1$s 권한을 부여할 수 있습니다. -1363 마지막 에러 +1366 마지막 에러 $set 6 MSGCAT_SET_INTERNAL 1 에러 서브 시스템에 에러 발생(라인 %1$d): @@ -1945,10 +1948,18 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC 320 '%1$s'는 Stored Procedure에서 지원하지 않는 결과 타입입니다 321 %TYPE 타입 지정은 PL/CSQL에서만 사용 가능합니다 322 테이블 컬럼 '%1$s.%2$s'이 정의되지 않았습니다 -323 Stored procedure/function '%1$s' 이(가) OUT 또는 IN OUT 인수를 가지고 있습니다. +323 저장 프로시저/함수 '%1$s' 이(가) OUT 또는 IN OUT 인수를 가지고 있습니다. 324 '%1$s'은 레코드 변수가 아닙니다. 325 언어를 지정하는 인수는 문자열 리터럴이어야 합니다. +325 언어를 지정하는 인수는 문자열 리터럴이어야 합니다. +326 저장 프로시저/함수 "%1$s"이(가) 존재하지 않습니다. +327 Out 매개변수에 DEFAULT를 할당하는 것은 허용되지 않습니다: '%1$s'. +328 오직 후행 기본 인수만 허용합니다: '%1$s' 에서 유효하지 않음. +329 %1$s에 대해 GRANT 옵션을 부여할 수 없습니다. + + + $set 9 MSGCAT_SET_PARSER_RUNTIME 1 가상 메모리 없음: %1$d 바이트를 할당할 수 없습니다. 2 트랜잭션 isolation 레벨은 1, 2, 3, 4, 5, 6 중에서 지정되어야 합니다. @@ -2232,3 +2243,11 @@ $set 16 MSGCAT_SET_LOG 28 복구 시점(%1$s)은 반드시 백업 시점(%2$s) 이후로 지정해야 합니다. \n 29 COMMENT: 보관 로그 %1$s는 로그 페이지 %2$lld 이전까지만 포함되어 HA 유틸리티에서 더 이상 사용되지 않습니다. 30 보관 로그의 개수가 허용 최대치를 초과했습니다. + +$set 17 MSGCAT_SET_GLOSSARY +1 클래스 +2 트리거 +3 시리얼 +4 서버 +5 동의어 +6 프로시저 diff --git a/msg/ko_KR.utf8/utils.msg b/msg/ko_KR.utf8/utils.msg index 3f4f0242362..ee3e2cee3b5 100644 --- a/msg/ko_KR.utf8/utils.msg +++ b/msg/ko_KR.utf8/utils.msg @@ -157,7 +157,7 @@ cubrid 관리자 유틸리티, 버전 %1$s\n\ gateway\n\ manager\n\ heartbeat\n\ - javasp\n\ + pl\n\ \n\ 가용한 관리자 유틸리티 이름:\n\ addvoldb\n\ @@ -262,11 +262,9 @@ cubrid 관리자 유틸리티, 버전 %1$s\n\ 42 인자가 잘못되었습니다.\n 43 파일(%1$s)을 열지 못했습니다.\n 44 cubrid 유틸리티, 버전 %1$s\n\ -사용법: %2$s javasp <명령어> [인자]\n\ +사용법: %2$s pl <명령어> [인자]\n\ \n\ 가용한 명령어:\n\ - start [데이터베이스 이름]\n\ - stop [데이터베이스 이름]\n\ restart [데이터베이스 이름]\n\ status [데이터베이스 이름]\n 45 cubrid 유틸리티, 버전 %1$s\n\ diff --git a/pl_engine/pl_server/build.gradle.kts b/pl_engine/pl_server/build.gradle.kts index 8ee0fbf52c2..c65c3b4f431 100644 --- a/pl_engine/pl_server/build.gradle.kts +++ b/pl_engine/pl_server/build.gradle.kts @@ -52,6 +52,9 @@ dependencies { implementation("org.apache.commons:commons-text:1.10.0") implementation("org.apache.commons:commons-collections4:4.4") implementation("org.apache.commons:commons-lang3:3.13.0") + implementation("commons-io:commons-io:2.15.1") + implementation("org.apache.commons:commons-compress:1.25.0") + implementation("org.antlr:antlr4-runtime:4.9.3") // CUBRID JDBC diff --git a/pl_engine/pl_server/src/main/antlr/PlcLexer.g4 b/pl_engine/pl_server/src/main/antlr/PlcLexer.g4 index bdf8847d2a2..a21cc43e38c 100644 --- a/pl_engine/pl_server/src/main/antlr/PlcLexer.g4 +++ b/pl_engine/pl_server/src/main/antlr/PlcLexer.g4 @@ -45,6 +45,7 @@ TRUNCATE: T R U N C A T E { staticSqlParenMatch++; checkFi // other keywords AND: A N D ; AS: A S ; +AUTHID: A U T H I D ; AUTONOMOUS_TRANSACTION: A U T O N O M O U S '_' T R A N S A C T I O N ; BEGIN: B E G I N ; BETWEEN: B E T W E E N ; @@ -52,6 +53,7 @@ BIGINT: B I G I N T ; BOOLEAN: B O O L E A N ; BY: B Y ; CASE: C A S E ; +CALLER: C A L L E R ; CHARACTER: C H A R A C T E R ; CHAR: C H A R ; CLOSE: C L O S E ; @@ -60,6 +62,7 @@ COMMIT: C O M M I T ; CONSTANT: C O N S T A N T ; CONTINUE: C O N T I N U E ; CREATE: C R E A T E ; +CURRENT_USER: C U R R E N T '_' U S E R ; CURSOR: C U R S O R ; DATE: D A T E ; DATETIME: D A T E T I M E ; @@ -70,6 +73,7 @@ DEC: D E C ; DECIMAL: D E C I M A L ; DECLARE: D E C L A R E ; DEFAULT: D E F A U L T ; +DEFINER: D E F I N E R ; DIV: D I V ; DOUBLE: D O U B L E ; ELSE: E L S E ; @@ -96,7 +100,7 @@ LANGUAGE: L A N G U A G E ; LIKE: L I K E ; LIST: L I S T ; LOOP: L O O P ; -MOD: ( M O D | '%' ) ; +MOD: M O D ; MULTISET: M U L T I S E T ; NOT: N O T ; NULL_: N U L L ; @@ -106,6 +110,7 @@ OPEN: O P E N ; OR_REPLACE: O R SPACE+ R E P L A C E ; OR: O R ; OUT: O U T ; +OWNER: O W N E R ; PERCENT_FOUND: '%' SPACE* F O U N D ; PERCENT_ISOPEN: '%' SPACE* I S O P E N ; PERCENT_NOTFOUND: '%' SPACE* N O T F O U N D ; diff --git a/pl_engine/pl_server/src/main/antlr/PlcParser.g4 b/pl_engine/pl_server/src/main/antlr/PlcParser.g4 index 33661dca9e6..4b950c81772 100644 --- a/pl_engine/pl_server/src/main/antlr/PlcParser.g4 +++ b/pl_engine/pl_server/src/main/antlr/PlcParser.g4 @@ -39,8 +39,13 @@ create_routine ; routine_definition - : (PROCEDURE | FUNCTION) identifier ( (LPAREN parameter_list RPAREN)? | LPAREN RPAREN ) (RETURN type_spec)? - (IS | AS) (LANGUAGE PLCSQL)? seq_of_declare_specs? body (SEMICOLON)? + : (PROCEDURE | FUNCTION) routine_uniq_name ( (LPAREN parameter_list RPAREN)? | LPAREN RPAREN ) (RETURN type_spec)? + (authid_spec)? (IS | AS) (LANGUAGE PLCSQL)? seq_of_declare_specs? body (SEMICOLON)? + ; + +routine_uniq_name + : (owner=identifier '.')? name=identifier + | '[' (owner=identifier '.')? name=identifier ']' /* rewritten query */ ; parameter_list @@ -48,8 +53,13 @@ parameter_list ; parameter - : parameter_name IN? type_spec (COMMENT CHAR_STRING)? # parameter_in - | parameter_name ( IN? OUT | INOUT ) type_spec (COMMENT CHAR_STRING)? # parameter_out + : parameter_name IN? type_spec default_value_part? (COMMENT CHAR_STRING)? # parameter_in + | parameter_name ( IN? OUT | INOUT ) type_spec (COMMENT CHAR_STRING)? # parameter_out + ; + +authid_spec + : AUTHID (DEFINER | OWNER) # authid_owner + | AUTHID (CALLER | CURRENT_USER) # authid_caller ; default_value_part @@ -211,7 +221,11 @@ return_statement ; procedure_call - : (DBMS_OUTPUT '.')? routine_name function_argument? + : proc_call_name function_argument? + ; + +proc_call_name + : (owner=identifier '.')? (DBMS_OUTPUT '.')? name=identifier ; body @@ -345,6 +359,7 @@ atom | record_field # field_exp | function_call # call_exp | identifier # id_exp + | keyword_builtin_func # builtin_func | case_expression # case_exp | SQL PERCENT_ROWCOUNT # sql_rowcount_exp // this must go before the cursor_attr_exp line | cursor_exp ( PERCENT_ISOPEN | PERCENT_FOUND | PERCENT_NOTFOUND | PERCENT_ROWCOUNT ) # cursor_attr_exp @@ -358,7 +373,29 @@ record_field ; function_call - : function_name function_argument + : func_call_name function_argument + ; + +func_call_name + : (owner=identifier '.')? name=func_name + ; + +func_name + : identifier + | keyword_builtin_func + ; + +keyword_builtin_func + : CURRENT_USER + | DATE + | DEFAULT + | IF + | INSERT + | MOD + | REPLACE + | TIME + | TIMESTAMP + | TRUNCATE ; relational_operator @@ -449,10 +486,6 @@ restricted_using_element : (IN)? expression ; -routine_name - : identifier - ; - parameter_name : identifier ; @@ -574,20 +607,7 @@ quoted_string identifier : REGULAR_ID | DELIMITED_ID - ; - -function_name - : identifier - | DATE - | DEFAULT - | IF - | INSERT - | MOD - | REPLACE | REVERSE - | TIME - | TIMESTAMP - | TRUNCATE ; diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/ExecuteThread.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/ExecuteThread.java index f4fb35083fc..1b46aa7a55e 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/ExecuteThread.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/ExecuteThread.java @@ -32,41 +32,47 @@ package com.cubrid.jsp; import com.cubrid.jsp.classloader.ClassLoaderManager; +import com.cubrid.jsp.code.CompiledCode; +import com.cubrid.jsp.code.CompiledCodeSet; +import com.cubrid.jsp.code.SourceCode; +import com.cubrid.jsp.compiler.MemoryJavaCompiler; import com.cubrid.jsp.context.Context; import com.cubrid.jsp.context.ContextManager; +import com.cubrid.jsp.data.AuthInfo; import com.cubrid.jsp.data.CUBRIDPacker; import com.cubrid.jsp.data.CUBRIDUnpacker; import com.cubrid.jsp.data.CompileInfo; +import com.cubrid.jsp.data.CompileRequest; import com.cubrid.jsp.data.DataUtilities; import com.cubrid.jsp.exception.ExecuteException; import com.cubrid.jsp.exception.TypeMismatchException; +import com.cubrid.jsp.protocol.BootstrapRequest; import com.cubrid.jsp.protocol.Header; import com.cubrid.jsp.protocol.PrepareArgs; import com.cubrid.jsp.protocol.RequestCode; import com.cubrid.jsp.value.Value; -import com.cubrid.jsp.value.ValueUtilities; import com.cubrid.plcsql.compiler.PlcsqlCompilerMain; import com.cubrid.plcsql.predefined.PlcsqlRuntimeError; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; -import java.io.File; -import java.io.FileWriter; import java.io.IOException; +import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.net.Socket; import java.nio.ByteBuffer; +import java.nio.file.Files; import java.nio.file.Path; import java.sql.SQLException; +import java.util.Base64; import java.util.List; -import javax.tools.JavaCompiler; -import javax.tools.ToolProvider; +import java.util.Map; +import org.apache.commons.compress.archivers.jar.JarArchiveEntry; +import org.apache.commons.compress.archivers.jar.JarArchiveOutputStream; public class ExecuteThread extends Thread { - - public static String charSet = "UTF-8"; - private Socket client; private DataInputStream input; @@ -117,11 +123,6 @@ public void closeSocket() { client = null; output = null; - // charSet = null; - } - - public void setCharSet(String conCharsetName) { - // this.charSet = conCharsetName; } @Override @@ -137,11 +138,6 @@ public void run() { * the following two request codes are for processing java stored procedure * routine */ - case RequestCode.PREPARE_ARGS: - { - processPrepare(); - break; - } case RequestCode.INVOKE_SP: { processStoredProcedure(); @@ -155,7 +151,12 @@ public void run() { break; } - /* the following request codes are for javasp utility */ + /* the following request codes are for system requests */ + case RequestCode.UTIL_BOOTSTRAP: + { + processBootstrap(); + break; + } case RequestCode.UTIL_PING: { String ping = Server.getServer().getServerName(); @@ -273,12 +274,15 @@ private Header listenCommand() throws Exception { ctx = ContextManager.getContext(header.id); ctx.checkHeader(header); - ByteBuffer payloadBuffer = - ByteBuffer.wrap( - inputBuffer.array(), - unpacker.getCurrentPosition(), - unpacker.getCurrentLimit() - unpacker.getCurrentPosition()); - ctx.getInboundQueue().add(payloadBuffer); + int startOffset = unpacker.getCurrentPosition(); + int payloadSize = unpacker.getCurrentLimit() - startOffset; + if (payloadSize > 0) { + ByteBuffer payloadBuffer = + ByteBuffer.wrap(inputBuffer.array(), startOffset, payloadSize); + + ctx.getInboundQueue().add(payloadBuffer); + } + return header; } @@ -304,67 +308,120 @@ public CUBRIDUnpacker getUnpacker() { return unpacker; } - private void processPrepare() throws Exception { + private void processStoredProcedure() throws Exception { unpacker.setBuffer(ctx.getInboundQueue().take()); + + // prepare if (prepareArgs == null) { prepareArgs = new PrepareArgs(unpacker); } else { prepareArgs.readArgs(unpacker); } - ctx.checkTranId(prepareArgs.getTranId()); - } - private void processStoredProcedure() throws Exception { - unpacker.setBuffer(ctx.getInboundQueue().take()); long id = unpacker.unpackBigint(); int tid = unpacker.unpackInt(); ctx.checkTranId(tid); StoredProcedure procedure = makeStoredProcedure(unpacker); + Value result = procedure.invoke(); /* send results */ sendResult(result, procedure); } + private void writeJar(CompiledCodeSet codeSet, OutputStream jarStream) throws IOException { + JarArchiveOutputStream jaos = null; + try { + jaos = new JarArchiveOutputStream(new BufferedOutputStream(jarStream)); + + for (Map.Entry entry : codeSet.getCodeList()) { + JarArchiveEntry jae = + new JarArchiveEntry(entry.getValue().getClassNameWithExtention()); + byte[] arr = entry.getValue().getByteCode(); + jae.setSize(arr.length); + jaos.putArchiveEntry(jae); + jaos.write(arr); + jaos.flush(); + // ByteArrayInputStream bis = new + // ByteArrayInputStream(entry.getValue().getByteCode()); + // IOUtils.copy(bis, jaos); + // bis.close(); + + jaos.closeArchiveEntry(); + } + } catch (IOException e) { + throw e; + } finally { + if (jaos != null) { + jaos.flush(); + jaos.finish(); + jaos.close(); + } + } + } + + private void processBootstrap() throws Exception { + unpacker.setBuffer(ctx.getInboundQueue().take()); + + int result = 1; // failed + try { + BootstrapRequest request = new BootstrapRequest(unpacker); + Server.bootstrap(request); + result = 0; // no error + } catch (Exception e) { + // ignore, 1 will be returned + Server.log(e); + } + + resultBuffer.clear(); /* prepare to put */ + packer.setBuffer(resultBuffer); + packer.packInt(result); + resultBuffer = packer.getBuffer(); + writeBuffer(resultBuffer); + } + private void processCompile() throws Exception { unpacker.setBuffer(ctx.getInboundQueue().take()); - boolean verbose = unpacker.unpackBool(); - String inSource = unpacker.unpackCString(); + + CompileRequest request = new CompileRequest(unpacker); + + // TODO: Pass CompileRequest directly to compilePLCSQL () + boolean verbose = false; + if (request.mode.contains("v")) { + verbose = true; + } + String inSource = request.code; + String owner = request.owner; CompileInfo info = null; try { - info = PlcsqlCompilerMain.compilePLCSQL(inSource, verbose); + info = PlcsqlCompilerMain.compilePLCSQL(inSource, owner, verbose); if (info.errCode == 0) { - Path javaFilePath = - ClassLoaderManager.getDynamicPath().resolve(info.className + ".java"); - File file = javaFilePath.toFile(); - if (file.exists()) { - file.delete(); - } - new FileWriter(file).append(info.translated).close(); - - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - if (compiler == null) { - throw new IllegalStateException( - "Cannot find the system Java compiler. Check that your class path includes tools.jar"); + MemoryJavaCompiler compiler = new MemoryJavaCompiler(); + SourceCode sCode = new SourceCode(info.className, info.translated); + CompiledCodeSet codeSet = compiler.compile(sCode); + + int mode = 1; // 0: temp file mode, 1: memory stream mode + byte[] data = null; + + // write to persistent + if (mode == 0) { + Path jarPath = + ClassLoaderManager.getDynamicPath().resolve(info.className + ".jar"); + OutputStream jarStream = Files.newOutputStream(jarPath); + writeJar(codeSet, jarStream); + data = Files.readAllBytes(jarPath); + Files.deleteIfExists(jarPath); + } else { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + writeJar(codeSet, baos); + data = baos.toByteArray(); } - Path cubrid_env_root = Server.getServer().getRootPath(); - String javacOpts[] = { - "-classpath", cubrid_env_root + "/java/pl_server.jar", file.getPath() - }; - - if (compiler.run(null, null, null, javacOpts) != 0) { - String command = - "javac " - + javaFilePath - + " -cp " - + cubrid_env_root - + "/java/pl_server.jar"; - throw new RuntimeException(command); - } + info.compiledType = 1; // TODO: always jar + info.compiledCode = Base64.getEncoder().encode(data); } } catch (Exception e) { info = @@ -373,6 +430,7 @@ private void processCompile() throws Exception { throw new RuntimeException(e); } finally { CUBRIDPacker packer = new CUBRIDPacker(ByteBuffer.allocate(1024)); + info.pack(packer); Context.getCurrentExecuteThread().sendCommand(RequestCode.COMPILE, packer.getBuffer()); } @@ -380,57 +438,47 @@ private void processCompile() throws Exception { private StoredProcedure makeStoredProcedure(CUBRIDUnpacker unpacker) throws Exception { String methodSig = unpacker.unpackCString(); + String authUser = unpacker.unpackCString(); + int lang = unpacker.unpackInt(); int paramCount = unpacker.unpackInt(); Value[] arguments = prepareArgs.getArgs(); - Value[] methodArgs = new Value[paramCount]; for (int i = 0; i < paramCount; i++) { - int pos = unpacker.unpackInt(); int mode = unpacker.unpackInt(); int type = unpacker.unpackInt(); + Value val = arguments[i]; - Value val = arguments[pos]; val.setMode(mode); val.setDbType(type); - - methodArgs[i] = val; } int returnType = unpacker.unpackInt(); boolean transactionControl = unpacker.unpackBool(); getCurrentContext().setTransactionControl(transactionControl); - storedProcedure = new StoredProcedure(methodSig, methodArgs, returnType); + storedProcedure = new StoredProcedure(methodSig, lang, authUser, arguments, returnType); return storedProcedure; } private void returnOutArgs(StoredProcedure sp, CUBRIDPacker packer) throws IOException, ExecuteException, TypeMismatchException { Value[] args = sp.getArgs(); - for (int i = 0; i < args.length; i++) { + for (int i = 0; args != null && i < args.length; i++) { if (args[i].getMode() > Value.IN) { - Value v = sp.makeOutValue(args[i].getResolved()); - packer.packValue( - ValueUtilities.resolveValue(args[i].getDbType(), v), - args[i].getDbType(), - this.charSet); + Value v = sp.makeOutValue(i); + packer.packValue(v, args[i].getDbType()); } } } private void sendResult(Value result, StoredProcedure procedure) throws IOException, ExecuteException, TypeMismatchException { - Object resolvedResult = null; - if (result != null) { - resolvedResult = ValueUtilities.resolveValue(procedure.getReturnType(), result); - } - resultBuffer.clear(); /* prepare to put */ packer.setBuffer(resultBuffer); packer.packInt(RequestCode.RESULT); packer.align(DataUtilities.MAX_ALIGNMENT); - packer.packValue(resolvedResult, procedure.getReturnType(), this.charSet); + packer.packValue(result, procedure.getReturnType()); returnOutArgs(procedure, packer); resultBuffer = packer.getBuffer(); @@ -472,4 +520,20 @@ private void sendError(String exception) throws IOException { resultBuffer = packer.getBuffer(); writeBuffer(resultBuffer); } + + private void sendAuthCommand(int command, String authName) throws Exception { + AuthInfo info = new AuthInfo(command, authName); + CUBRIDPacker packer = new CUBRIDPacker(ByteBuffer.allocate(128)); + packer.packInt(RequestCode.REQUEST_CHANGE_AUTH_RIGHTS); + info.pack(packer); + Context.getCurrentExecuteThread().sendCommand(packer.getBuffer()); + + ByteBuffer responseBuffer = Context.getCurrentExecuteThread().receiveBuffer(); + CUBRIDUnpacker unpacker = new CUBRIDUnpacker(responseBuffer); + /* read header, dummy */ + Header header = new Header(unpacker); + ByteBuffer payload = unpacker.unpackBuffer(); + unpacker.setBuffer(payload); + int responseCode = unpacker.unpackInt(); + } } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/Server.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/Server.java index 770c8d525ac..10418cd05e2 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/Server.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/Server.java @@ -32,6 +32,8 @@ package com.cubrid.jsp; import com.cubrid.jsp.classloader.ClassLoaderManager; +import com.cubrid.jsp.exception.TypeMismatchException; +import com.cubrid.jsp.protocol.BootstrapRequest; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; @@ -41,7 +43,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.time.ZoneOffset; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; @@ -243,6 +244,27 @@ public static void stop(int status) { } } + public static void bootstrap(BootstrapRequest request) { + SysParam[] systemParameters = request.getSystemParameters(); + for (SysParam sysParam : systemParameters) { + config.getSystemParameters().put(sysParam.getParamId(), sysParam); + } + + config.initializeCharset(); + } + + public static boolean getSystemParameterBool(int id) { + try { + SysParam param = config.getSystemParameters().get(id); + if (param != null) { + return param.getParamValue().toInt() != 0; + } + } catch (TypeMismatchException e) { + } + + return false; + } + public static void main(String[] args) throws Exception { Server.start(args); } @@ -266,40 +288,7 @@ public boolean getShutdown() { return shutdown.get(); } - // ---------------------------------------------------------------------- - // The following two methods are temporary mock implementation - - public static final int SYS_PARAM_COMPAT_NUMERIC_DIVISION_SCALE = 1; - public static final int SYS_PARAM_ORACLE_COMPAT_NUMBER_BEHAVIOR = 2; - public static final int SYS_PARAM_ORACLE_STYLE_EMPTY_STRING = 3; - public static final int SYS_PARAM_TIMEZONE = 4; - - public static boolean getSystemParameterBool(int code) { - switch (code) { - case SYS_PARAM_COMPAT_NUMERIC_DIVISION_SCALE: - return false; - case SYS_PARAM_ORACLE_COMPAT_NUMBER_BEHAVIOR: - return false; - case SYS_PARAM_ORACLE_STYLE_EMPTY_STRING: - return false; - default: - assert (false); - return false; - } - } - - private static final ZoneOffset tz = ZoneOffset.of("+09:00"); - - public static ZoneOffset getSystemParameterTimezone(int code) { - switch (code) { - case SYS_PARAM_TIMEZONE: - return tz; - default: - assert (false); - return null; - } + public static ServerConfig getConfig() { + return config; } - - // - // ---------------------------------------------------------------------- } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/ServerConfig.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/ServerConfig.java index 4f71ee1ad76..d4b0f6c02f4 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/ServerConfig.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/ServerConfig.java @@ -1,6 +1,42 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + package com.cubrid.jsp; import java.io.File; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.HashMap; import org.apache.commons.lang3.StringUtils; public class ServerConfig { @@ -20,6 +56,12 @@ public class ServerConfig { private final String socketType; // TCP or UDS private final String socketInfo; // port number or socket file path + // System settings + private HashMap systemParameters; + + private Charset serverCharset; + private ZoneId serverTimeZone; + public ServerConfig( String name, String version, String rPath, String dbPath, String socketInfo) { this.name = name; @@ -37,6 +79,10 @@ public ServerConfig( this.socketInfo = socketInfo; this.socketType = StringUtils.isNumeric(socketInfo) ? "TCP" : "UDS"; + + this.systemParameters = new HashMap(); + this.serverTimeZone = null; + this.serverCharset = StandardCharsets.UTF_8; } public String getName() { @@ -70,4 +116,63 @@ public String getDatabasePath() { public String getSocketInfo() { return socketInfo; } + + public HashMap getSystemParameters() { + return systemParameters; + } + + public ZoneId getTimeZone() { + if (serverTimeZone == null) { + // get the timezone from the system parameters + SysParam sysParam = systemParameters.get(SysParam.TIMEZONE); + serverTimeZone = ZoneId.of(sysParam.getParamValue().toString()); + } + + if (serverTimeZone == null) { + // if the timezone is not set, use the default timezone (UTC) + serverTimeZone = ZoneOffset.UTC; + } + + return serverTimeZone; + } + + public Charset getServerCharset() { + return serverCharset; + } + + public int getServerCodesetId() { + return SysParam.getCodesetId(serverCharset); + } + + public void initializeCharset() { + SysParam sysParam = systemParameters.get(SysParam.INTL_COLLATION); + String collation = sysParam.getParamValue().toString(); + String codeset = null; + String[] codesetList = collation.split("_"); + if (codesetList == null) { + codeset = collation; + } else { + codeset = codesetList[0]; + } + + // tune the codeset name java understands + if (codeset.equalsIgnoreCase("utf-8") || codeset.equalsIgnoreCase("utf8")) { + codeset = "UTF-8"; + } else if (codeset.equalsIgnoreCase("ksc-euc") || codeset.equalsIgnoreCase("euckr")) { + codeset = "EUC-KR"; + } else if (codeset.equalsIgnoreCase("iso88591")) { + codeset = "ISO-8859-1"; + } else if (codeset.equalsIgnoreCase("ascii")) { + codeset = "UTF-8"; // ascii is a subset of UTF-8 + } + + try { + serverCharset = Charset.forName(codeset); + } catch (Exception e) { + // java.nio.charset.IllegalCharsetNameException + Server.log(e); + serverCharset = StandardCharsets.UTF_8; + } + System.setProperty("file.encoding", serverCharset.toString()); + } } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/StoredProcedure.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/StoredProcedure.java index 325da85eb0c..85c5db86ef0 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/StoredProcedure.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/StoredProcedure.java @@ -31,29 +31,23 @@ package com.cubrid.jsp; +import com.cubrid.jsp.classloader.ServerClassLoader; +import com.cubrid.jsp.code.ClassAccess; +import com.cubrid.jsp.code.CompiledCodeSet; +import com.cubrid.jsp.code.Signature; +import com.cubrid.jsp.context.Context; import com.cubrid.jsp.context.ContextManager; import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.ExecuteException; import com.cubrid.jsp.exception.TypeMismatchException; -import com.cubrid.jsp.value.BooleanValue; -import com.cubrid.jsp.value.ByteValue; -import com.cubrid.jsp.value.DateValue; -import com.cubrid.jsp.value.DatetimeValue; -import com.cubrid.jsp.value.DoubleValue; -import com.cubrid.jsp.value.FloatValue; -import com.cubrid.jsp.value.IntValue; -import com.cubrid.jsp.value.LongValue; -import com.cubrid.jsp.value.NumericValue; -import com.cubrid.jsp.value.OidValue; -import com.cubrid.jsp.value.ResultSetValue; +import com.cubrid.jsp.value.NullValue; import com.cubrid.jsp.value.SetValue; -import com.cubrid.jsp.value.ShortValue; -import com.cubrid.jsp.value.StringValue; -import com.cubrid.jsp.value.TimeValue; import com.cubrid.jsp.value.Value; +import com.cubrid.jsp.value.ValueUtilities; import cubrid.sql.CUBRIDOID; import java.lang.reflect.Method; import java.math.BigDecimal; +import java.sql.Connection; import java.sql.Date; import java.sql.ResultSet; import java.sql.Time; @@ -61,32 +55,99 @@ public class StoredProcedure { private String signature; + private String authUser; private Value[] args; private int returnType; + private int lang; + + private Class targetClass; private TargetMethod target; private Object[] cachedResolved; - public StoredProcedure(String signature, Value[] args, int returnType) throws Exception { + // METHOD_TYPE in method_def.hpp + private static final int LANG_JAVASP = 3; + private static final int LANG_PLCSQL = 4; + + public StoredProcedure( + String signature, int lang, String authUser, Value[] args, int returnType) + throws Exception { this.signature = signature; + this.authUser = authUser; this.args = args; this.returnType = returnType; - this.target = - ContextManager.getContextofCurrentThread().getTargetMethodCache().get(signature); + this.lang = lang; + + this.target = findTargetMethod(signature); + this.cachedResolved = null; checkArgs(); } + private TargetMethod findTargetMethod(String sigString) throws Exception { + Context ctx = ContextManager.getContextofCurrentThread(); + + Connection conn = ctx.getConnection(); + Signature sig = Signature.parse(sigString); + + Class c = null; + ClassNotFoundException ex = null; + if (lang == LANG_PLCSQL) { + try { + c = ctx.getSessionCLManager().findClass(sig.getClassName()); + if (c == null) { + CompiledCodeSet codeset = ClassAccess.getObjectCode(conn, sig); + if (codeset != null) { + c = ctx.getSessionCLManager().loadClass(codeset); + } + } + } catch (ClassNotFoundException e) { + ex = e; + } + } else if (lang == LANG_JAVASP) { + try { + c = ctx.getOldClassLoader().loadClass(sig.getClassName()); + } catch (ClassNotFoundException e) { + ex = e; + } + } else { + assert false; + throw new ClassNotFoundException(sig.getClassName()); + } + + // find a class in static directory and system loader + if (c == null) { + c = ServerClassLoader.getInstance().loadClass(sig.getClassName()); + } + + if (c == null) { + throw ex; + } + + targetClass = c; + TargetMethod target = new TargetMethod(sig); + return target; + } + public Object[] getResolved() { + if (args == null) { + return null; + } + Object[] resolved = new Object[args.length]; for (int i = 0; i < args.length; i++) { resolved[i] = args[i].getResolved(); } + return resolved; } private void checkArgs() throws TypeMismatchException { + if (args == null) { + return; + } + Class[] argsTypes = target.getArgsTypes(); if (argsTypes.length != args.length) { throw new TypeMismatchException( @@ -95,7 +156,6 @@ private void checkArgs() throws TypeMismatchException { + ", but " + args.length); } - for (int i = 0; i < argsTypes.length; i++) { Object resolved; if (args[i] == null) { @@ -280,104 +340,26 @@ private void checkArgs() throws TypeMismatchException { } public Value invoke() throws Exception { - Method m = target.getMethod(); + Method m = target.getMethod(targetClass); if (cachedResolved == null) { cachedResolved = getResolved(); } Object result = m.invoke(null, cachedResolved); - return makeReturnValue(result); - } - - public Value makeOutValue(Object object) throws ExecuteException, TypeMismatchException { - Object obj = null; - if (object instanceof byte[]) { - obj = new Byte(((byte[]) object)[0]); - } else if (object instanceof short[]) { - obj = new Short(((short[]) object)[0]); - } else if (object instanceof int[]) { - obj = new Integer(((int[]) object)[0]); - } else if (object instanceof long[]) { - obj = new Long(((long[]) object)[0]); - } else if (object instanceof float[]) { - obj = new Float(((float[]) object)[0]); - } else if (object instanceof double[]) { - obj = new Double(((double[]) object)[0]); - } else if (object instanceof byte[][]) { - obj = ((byte[][]) object)[0]; - } else if (object instanceof short[][]) { - obj = ((short[][]) object)[0]; - } else if (object instanceof int[][]) { - obj = ((int[][]) object)[0]; - } else if (object instanceof long[][]) { - obj = ((long[][]) object)[0]; - } else if (object instanceof float[][]) { - obj = ((float[][]) object)[0]; - } else if (object instanceof double[][]) { - obj = ((double[][]) object)[0]; - } else if (object instanceof Object[]) { - obj = ((Object[]) object)[0]; - } - - return makeReturnValue(obj); + return ValueUtilities.createValueFrom(result); } - public Value makeReturnValue(Object o) throws ExecuteException, TypeMismatchException { - Value val = null; - - if (o == null) { - return null; - } else if (o instanceof Boolean) { - val = new BooleanValue(((Boolean) o).booleanValue()); - } else if (o instanceof Byte) { - val = new ByteValue(((Byte) o).byteValue()); - } else if (o instanceof Character) { - val = new StringValue(((Character) o).toString()); - } else if (o instanceof Short) { - val = new ShortValue(((Short) o).shortValue()); - } else if (o instanceof Integer) { - val = new IntValue(((Integer) o).intValue()); - } else if (o instanceof Long) { - val = new LongValue(((Long) o).longValue()); - } else if (o instanceof Float) { - val = new FloatValue(((Float) o).floatValue()); - } else if (o instanceof Double) { - val = new DoubleValue(((Double) o).doubleValue()); - } else if (o instanceof BigDecimal) { - val = new NumericValue(((BigDecimal) o)); - } else if (o instanceof String) { - val = new StringValue((String) o); - } else if (o instanceof java.sql.Date) { - val = new DateValue((java.sql.Date) o); - } else if (o instanceof java.sql.Time) { - val = new TimeValue((java.sql.Time) o); - } else if (o instanceof java.sql.Timestamp) { - val = - new DatetimeValue( - (java.sql.Timestamp) - o); // DatetimeValue allows more values than TimestampValue - } else if (o instanceof CUBRIDOID) { - val = new OidValue((CUBRIDOID) o); - } else if (o instanceof ResultSet) { - val = new ResultSetValue((ResultSet) o); - } else if (o instanceof byte[]) { - val = new SetValue((byte[]) o); - } else if (o instanceof short[]) { - val = new SetValue((short[]) o); - } else if (o instanceof int[]) { - val = new SetValue((int[]) o); - } else if (o instanceof long[]) { - val = new SetValue((long[]) o); - } else if (o instanceof float[]) { - val = new SetValue((float[]) o); - } else if (o instanceof double[]) { - val = new SetValue((double[]) o); - } else if (o instanceof Object[]) { - val = new SetValue((Object[]) o); + public Value makeOutValue(int idx) throws TypeMismatchException, ExecuteException { + Class[] argsTypes = target.getArgsTypes(); + if (argsTypes[idx].isArray()) { + Value resolved = ValueUtilities.createValueFrom(cachedResolved[idx]); + if (resolved instanceof SetValue) { + return ((SetValue) resolved).toValueArray()[0]; + } else { + return resolved; + } } else { - throw new ExecuteException("Not supported data type: '" + o.getClass().getName() + "'"); + return new NullValue(); } - - return val; } public int getReturnType() { @@ -399,4 +381,8 @@ public String getSignature() { public TargetMethod getTarget() { return target; } + + public String getAuthUser() { + return authUser; + } } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/SysParam.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/SysParam.java new file mode 100644 index 00000000000..eb3bff91b73 --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/SysParam.java @@ -0,0 +1,103 @@ +package com.cubrid.jsp; + +import com.cubrid.jsp.data.CUBRIDUnpacker; +import com.cubrid.jsp.exception.TypeMismatchException; +import com.cubrid.jsp.protocol.UnPackableObject; +import com.cubrid.jsp.value.Value; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public class SysParam implements UnPackableObject { + + // see src/base/system_parameter.h + public static final int ORACLE_STYLE_EMPTY_STRING = 95; + public static final int COMPAT_NUMERIC_DIVISION_SCALE = 100; + public static final int INTL_NUMBER_LANG = 193; + public static final int INTL_DATE_LANG = 194; + public static final int INTL_COLLATION = 206; + public static final int TIMEZONE = 249; + public static final int ORACLE_COMPAT_NUMBER_BEHAVIOR = 334; + + // codeset + public static final int CODESET_ASCII = 0; + public static final int CODESET_RAW_BITS = 1; + public static final int CODESET_RAW_BYTES = 2; + public static final int CODESET_ISO88591 = 3; + public static final int CODESET_KSC5601_EUC = 4; + public static final int CODESET_UTF8 = 5; + + public static Charset CHARSET_EUCKR = null; + + public static String getCodesetString(int codeset) { + switch (codeset) { + case CODESET_ASCII: + return StandardCharsets.US_ASCII.toString(); + case CODESET_RAW_BITS: + case CODESET_RAW_BYTES: + break; + case CODESET_ISO88591: + return StandardCharsets.ISO_8859_1.toString(); + case CODESET_KSC5601_EUC: + if (CHARSET_EUCKR == null) { + CHARSET_EUCKR = Charset.forName("EUC-KR"); + } + return CHARSET_EUCKR.toString(); + default: + break; + } + + return "UTF-8"; // default + } + + public static int getCodesetId(Charset charset) { + if (charset.equals(StandardCharsets.US_ASCII)) { + return CODESET_ASCII; + } else if (charset.equals(StandardCharsets.ISO_8859_1)) { + return CODESET_ISO88591; + } else if (charset.equals(CHARSET_EUCKR)) { + return CODESET_KSC5601_EUC; + } else { + return CODESET_UTF8; + } + } + + private int paramId; + private int paramType; + private Value paramValue; + + public SysParam(CUBRIDUnpacker unpacker) { + unpack(unpacker); + } + + public int getParamId() { + return paramId; + } + + public Value getParamValue() { + return paramValue; + } + + public int getParamType() { + return paramType; + } + + public String toString() { + return "SystemParameter [paramId=" + + paramId + + ", paramType=" + + paramType + + ", paramValue=" + + paramValue + + "]"; + } + + @Override + public void unpack(CUBRIDUnpacker unpacker) { + try { + this.paramId = unpacker.unpackInt(); // paramId + this.paramType = unpacker.unpackInt(); // paramType + this.paramValue = unpacker.unpackValue(paramType); + } catch (TypeMismatchException e) { + } + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/TargetMethod.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/TargetMethod.java index 54ee4bb6e33..ebce29579a3 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/TargetMethod.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/TargetMethod.java @@ -31,8 +31,7 @@ package com.cubrid.jsp; -import com.cubrid.jsp.context.Context; -import com.cubrid.jsp.context.ContextManager; +import com.cubrid.jsp.code.Signature; import com.cubrid.jsp.exception.ExecuteException; import cubrid.sql.CUBRIDOID; import java.lang.reflect.Method; @@ -55,47 +54,10 @@ public class TargetMethod { initdescriptorMap(); } - public TargetMethod(String signature) throws Exception { - int argStart = signature.indexOf('(') + 1; - if (argStart < 0) { - throw new IllegalArgumentException("Parenthesis '(' not found"); - } - int argEnd = signature.indexOf(')'); - if (argEnd < 0) { - throw new IllegalArgumentException("Parenthesis ')' not found"); - } - int nameStart = signature.substring(0, argStart).lastIndexOf('.') + 1; - - if (signature.charAt(0) == '\'') { - className = signature.substring(1, nameStart - 1).trim(); - } else { - className = signature.substring(0, nameStart - 1).trim(); - } - - methodName = signature.substring(nameStart, argStart - 1).trim(); - String args = signature.substring(argStart, argEnd); - argsTypes = classesFor(args); - } - - private Class getClass(String name) throws ClassNotFoundException { - Context ctx = ContextManager.getContextofCurrentThread(); - ClassLoader cl = ctx.getClassLoader(); - Class c = null; - try { - c = cl.loadClass(name); - assert c != null; - return c; - } catch (ClassNotFoundException e) { - // ignore - } - - try { - c = Server.class.getClassLoader().loadClass(name); - assert c != null; - return c; - } catch (ClassNotFoundException e) { - throw e; - } + public TargetMethod(Signature signature) throws Exception { + className = signature.getClassName(); + methodName = signature.getMethodName(); + argsTypes = classesFor(signature.getArgs()); } private Class[] classesFor(String args) throws ClassNotFoundException, ExecuteException { @@ -141,7 +103,10 @@ private Class classFor(String className) throws ClassNotFoundException, Execu if (argClassMap.containsKey(className)) { return argClassMap.get(className); } else { - return getClass(className); + // TODO: + // return ClassAccess.getClass(ContextManager.getContextofCurrentThread(), className); + // unknown class + throw new ClassNotFoundException(className); } } @@ -182,6 +147,18 @@ private static void initArgClassMap() { argClassMap.put("java.lang.Double", Double.class); argClassMap.put("java.lang.String", String.class); argClassMap.put("java.lang.Object", Object.class); + + argClassMap.put("Boolean", Boolean.class); + argClassMap.put("Byte", Byte.class); + argClassMap.put("Character", Character.class); + argClassMap.put("Short", Short.class); + argClassMap.put("Integer", Integer.class); + argClassMap.put("Long", Long.class); + argClassMap.put("Float", Float.class); + argClassMap.put("Double", Double.class); + argClassMap.put("String", String.class); + argClassMap.put("Object", Object.class); + argClassMap.put("java.math.BigDecimal", BigDecimal.class); argClassMap.put("java.sql.Date", Date.class); argClassMap.put("java.sql.Time", Time.class); @@ -198,6 +175,18 @@ private static void initArgClassMap() { argClassMap.put("[Ljava.lang.Double;", Double[].class); argClassMap.put("[Ljava.lang.String;", String[].class); argClassMap.put("[Ljava.lang.Object;", Object[].class); + + argClassMap.put("[LBoolean;", Boolean[].class); + argClassMap.put("[LByte;", Byte[].class); + argClassMap.put("[LCharacter;", Character[].class); + argClassMap.put("[LShort;", Short[].class); + argClassMap.put("[LInteger;", Integer[].class); + argClassMap.put("[LLong;", Long[].class); + argClassMap.put("[LFloat;", Float[].class); + argClassMap.put("[LDouble;", Double[].class); + argClassMap.put("[LString;", String[].class); + argClassMap.put("[LObject;", Object[].class); + argClassMap.put("[Ljava.math.BigDecimal;", BigDecimal[].class); argClassMap.put("[Ljava.sql.Date;", Date[].class); argClassMap.put("[Ljava.sql.Time;", Time[].class); @@ -219,12 +208,7 @@ private static void initdescriptorMap() { descriptorMap.put("double", "D"); } - public Method getMethod() - throws SecurityException, NoSuchMethodException, ClassNotFoundException { - Class c = getClass(className); - if (c == null) { - throw new ClassNotFoundException(className); - } + public Method getMethod(Class c) throws SecurityException, NoSuchMethodException { try { return c.getMethod(methodName, argsTypes); } catch (NoSuchMethodException e) { diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/TargetMethodCache.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/TargetMethodCache.java index 60a6c500e2b..0dd3c7a9e3e 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/TargetMethodCache.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/TargetMethodCache.java @@ -45,7 +45,8 @@ public TargetMethod get(String signature) throws Exception { method = methods.get(signature); if (method == null) { - method = new TargetMethod(signature); + // TODO (CBRD-25370) : disabled temporary + // method = new TargetMethod(signature); methods.put(signature, method); } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/classloader/SessionClassLoader.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/classloader/SessionClassLoader.java new file mode 100644 index 00000000000..7c570498796 --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/classloader/SessionClassLoader.java @@ -0,0 +1,93 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.classloader; + +import com.cubrid.jsp.code.CompiledCode; +import com.cubrid.jsp.code.CompiledCodeSet; +import java.util.Map.Entry; +import java.util.UUID; + +public class SessionClassLoader extends ClassLoader { + + private String id = null; + private CompiledCodeSet code = null; + + public SessionClassLoader(CompiledCodeSet code) { + id = UUID.randomUUID().toString(); + this.code = code; + } + + public String getId() { + return id; + } + + public CompiledCodeSet getCode() { + return code; + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + Class mainCls = findLoadedClass(name); + if (mainCls != null) { + // already loaded + } else { + try { + mainCls = super.loadClass(name); + if (mainCls != null) { + return mainCls; + } + } catch (ClassNotFoundException e) { + // ignore + } + + // find in codesets + if (code != null) { + for (Entry entry : code.getCodeList()) { + Class cls = null; + String className = entry.getKey(); + byte[] classBytes = entry.getValue().getByteCode(); + cls = defineClass(className, classBytes, 0, classBytes.length); + if (name.equals(className)) { + mainCls = cls; + } + } + } + } + + return mainCls; + } + + public void clear() { + id = null; + code = null; + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/classloader/SessionClassLoaderGroup.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/classloader/SessionClassLoaderGroup.java new file mode 100644 index 00000000000..cbb6f52bd00 --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/classloader/SessionClassLoaderGroup.java @@ -0,0 +1,38 @@ +package com.cubrid.jsp.classloader; + +import com.cubrid.jsp.code.CompiledCodeSet; +import java.util.HashMap; +import java.util.Map; + +public class SessionClassLoaderGroup { + + Map classLoaders = null; + + public SessionClassLoaderGroup() { + classLoaders = new HashMap<>(); + } + + public void clear() { + classLoaders.clear(); + classLoaders = null; + } + + public Class loadClass(CompiledCodeSet code) throws ClassNotFoundException { + String name = code.getMainClassName(); + SessionClassLoader cl = classLoaders.get(name); + if (cl != null) { + CompiledCodeSet loadedCode = cl.getCode(); + if (loadedCode.getTimeStamp() != code.getTimeStamp()) { + // create new SessionClassLoader + cl.clear(); + cl = new SessionClassLoader(code); + classLoaders.put(name, cl); + } + } else { + cl = new SessionClassLoader(code); + classLoaders.put(name, cl); + } + + return cl.loadClass(name); + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/classloader/SessionClassLoaderManager.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/classloader/SessionClassLoaderManager.java new file mode 100644 index 00000000000..e84a6e58bfb --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/classloader/SessionClassLoaderManager.java @@ -0,0 +1,68 @@ +package com.cubrid.jsp.classloader; + +import com.cubrid.jsp.code.CompiledCodeSet; +import com.cubrid.jsp.code.MemoryClass; +import java.util.HashMap; +import java.util.Map; + +public class SessionClassLoaderManager { + + private long id; + + private Map sessionScopedLoadedCode; //
+ + private SessionClassLoaderGroup sessionClassLoaderGroup; + + public SessionClassLoaderManager(long id) { + this.id = id; + sessionScopedLoadedCode = new HashMap<>(); + sessionClassLoaderGroup = new SessionClassLoaderGroup(); + } + + public Class loadClass(CompiledCodeSet code) throws ClassNotFoundException { + if (code == null) { + return null; + } + + String className = code.getMainClassName(); + MemoryClass mCls = null; + if (!sessionScopedLoadedCode.containsKey(className)) { + mCls = new MemoryClass(className); + mCls.setCode(code); + sessionScopedLoadedCode.put(className, mCls); + } + + Class loadedClass = sessionClassLoaderGroup.loadClass(code); + if (mCls != null && loadedClass != null) { + mCls.setLoadedClass(loadedClass); + } + + return loadedClass; + } + + public Class findClass(String mainClassName) { + MemoryClass mCls = null; + if (sessionScopedLoadedCode.containsKey(mainClassName)) { + mCls = sessionScopedLoadedCode.get(mainClassName); + } + + if (mCls != null) { + return mCls.getLoadedClass(); + } + + return null; + } + + public void clear() { + sessionScopedLoadedCode.clear(); + + if (sessionClassLoaderGroup != null) { + sessionClassLoaderGroup.clear(); + } + sessionClassLoaderGroup = new SessionClassLoaderGroup(); + } + + public long getId() { + return id; + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/ClassAccess.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/ClassAccess.java new file mode 100644 index 00000000000..fffad3ce5ff --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/ClassAccess.java @@ -0,0 +1,141 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ +package com.cubrid.jsp.code; + +import com.cubrid.jsp.context.Context; +import com.cubrid.jsp.data.CUBRIDPacker; +import com.cubrid.jsp.data.CUBRIDUnpacker; +import com.cubrid.jsp.exception.TypeMismatchException; +import com.cubrid.jsp.protocol.Header; +import com.cubrid.jsp.protocol.RequestCode; +import com.cubrid.jsp.value.Value; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Base64; + +public class ClassAccess { + public static String getCodeMeta(Connection conn, String name) throws SQLException { + String ts = null; + String sql = + "SELECT created_time, is_static, is_system_generated FROM _db_stored_procedure_code WHERE name = ?"; + PreparedStatement prepStmt = conn.prepareStatement(sql); + prepStmt.setString(1, name); + + ResultSet rs = prepStmt.executeQuery(); + if (rs.next()) { + ts = rs.getString(1); + } + rs.close(); + return ts; + } + + public static String getTransactionKey(Connection conn, String name) + throws IOException, TypeMismatchException { + String ts = null; + + sendGetCodeAttr("created_time"); + + Value val = receiveCodeAttrValue(); + if (val != null) { + ts = val.toString(); + } + + return ts; + } + + public static byte[] getObjectCodeBytes(Connection conn, String name) + throws IOException, TypeMismatchException { + byte[] jar = null; + + sendGetCodeAttr("ocode"); + + Value val = receiveCodeAttrValue(); + if (val != null) { + String base64Str = val.toString(); + jar = Base64.getDecoder().decode(base64Str); + } + + return jar; + } + + public static CompiledCodeSet getObjectCode(Connection conn, Signature sig) throws Exception { + CompiledCodeSet code = null; + String className = sig.getClassName(); + + String tKey = null; + try { + tKey = getTransactionKey(conn, className); + } catch (Exception e) { + } + + if (tKey == null) { + return null; + } + + byte[] jarCode = ClassAccess.getObjectCodeBytes(conn, className); + if (jarCode != null) { + code = CompiledCodeSet.loadFromJar(className, jarCode); + code.setTimestamp(tKey); + } + + return code; + } + + private static void sendGetCodeAttr(String attr_name) throws IOException { + CUBRIDPacker packer = new CUBRIDPacker(ByteBuffer.allocate(1024)); + packer.packInt(RequestCode.REQUEST_CODE_ATTR); + packer.packString(attr_name); + Context.getCurrentExecuteThread().sendCommand(packer.getBuffer()); + } + + private static Value receiveCodeAttrValue() throws IOException, TypeMismatchException { + ByteBuffer responseBuffer = Context.getCurrentExecuteThread().receiveBuffer(); + CUBRIDUnpacker unpacker = new CUBRIDUnpacker(responseBuffer); + + Header header = new Header(unpacker); + ByteBuffer payload = unpacker.unpackBuffer(); + + unpacker.setBuffer(payload); + + int error = unpacker.unpackInt(); + if (error == 0) { + int param_type = unpacker.unpackInt(); + Value val = unpacker.unpackValue(param_type); + return val; + } + + return null; + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/CompiledCode.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/CompiledCode.java new file mode 100644 index 00000000000..5336d24707b --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/CompiledCode.java @@ -0,0 +1,89 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.code; + +import com.cubrid.jsp.Server; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import javax.tools.SimpleJavaFileObject; + +public class CompiledCode extends SimpleJavaFileObject { + private String className = null; + private ByteArrayOutputStream baos = null; + + private byte[] byteCode = null; + + public CompiledCode(String className) throws java.net.URISyntaxException { + super(new URI(className), Kind.CLASS); + + int idx = className.indexOf("."); + if (idx != -1) { + this.className = className.substring(0, idx); + + } else { + this.className = className; + } + this.baos = new ByteArrayOutputStream(); + } + + public String getClassName() { + return className; + } + + public String getClassNameWithExtention() { + return className + ".class"; + } + + public byte[] getByteCode() { + if (byteCode == null) { + byteCode = baos.toByteArray(); + try { + baos.close(); + } catch (IOException e) { + // ignore + } + } + return byteCode; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return new String(getByteCode(), Server.getConfig().getServerCharset()); + } + + @Override + public OutputStream openOutputStream() throws IOException { + return baos; + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/CompiledCodeSet.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/CompiledCodeSet.java new file mode 100644 index 00000000000..839593a3510 --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/CompiledCodeSet.java @@ -0,0 +1,133 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.code; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.commons.compress.archivers.jar.JarArchiveEntry; +import org.apache.commons.compress.archivers.jar.JarArchiveInputStream; + +public class CompiledCodeSet { + + private String mainClass = null; + private long timestamp = -1; + private Map codeMap = null; + + public CompiledCodeSet(String mainClass, Collection codeList) { + this.mainClass = mainClass; + this.codeMap = + codeList.stream() + .collect(Collectors.toMap(CompiledCode::getClassName, item -> item)); + } + + public String getMainClassName() { + return mainClass; + } + + public void add(CompiledCode c) { + codeMap.put(c.getClassName(), c); + } + + public void addAll(Collection cl) { + Map map = + cl.stream().collect(Collectors.toMap(CompiledCode::getClassName, item -> item)); + codeMap.putAll(map); + } + + public Set> getCodeList() { + return codeMap.entrySet(); + } + + public void setTimestamp(String tsString) { + timestamp = Long.parseLong(tsString); + } + + public void setTimestamp(long ts) { + timestamp = ts; + } + + public long getTimeStamp() { + return timestamp; + } + + public void clear() { + mainClass = null; + codeMap.clear(); + } + + public static CompiledCodeSet loadFromJar(String mainClass, byte[] jarString) throws Exception { + + List codeList = new ArrayList<>(); + + try (final JarArchiveInputStream jarIn = + new JarArchiveInputStream(new ByteArrayInputStream(jarString))) { + JarArchiveEntry jarEntry; + while ((jarEntry = jarIn.getNextEntry()) != null) { + if (jarEntry.isDirectory()) { + continue; + } + final String key = jarEntry.getName(); + CompiledCode c = new CompiledCode(key); + OutputStream os = c.openOutputStream(); + + final long fileSize = jarEntry.getSize(); + byte[] buffer = null; + if (fileSize > 0) { + + buffer = new byte[(int) fileSize]; + } else { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + while (true) { + int qwe = jarIn.read(); + if (qwe == -1) break; + baos.write(qwe); + } + buffer = baos.toByteArray(); + } + jarIn.read(buffer); + os.write(buffer); + // IOUtils.copy (jarIn, os, fileSize); + codeList.add(c); + } + } + + return new CompiledCodeSet(mainClass, codeList); + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/MemoryClass.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/MemoryClass.java new file mode 100644 index 00000000000..0bbfaf901f6 --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/MemoryClass.java @@ -0,0 +1,70 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.code; + +// cacheable Class object in-memory +public class MemoryClass { + + private String className = null; + private CompiledCodeSet loadedCode = null; + private Class loadedClass = null; + + public MemoryClass(String className) { + this.className = className; + } + + public String getClassName() { + return className; + } + + public void setCode(CompiledCodeSet codeset) { + clear(); + this.loadedCode = codeset; + } + + public Class getLoadedClass() { + return loadedClass; + } + + public void setLoadedClass(Class loadedClass) { + this.loadedClass = loadedClass; + } + + public void clear() { + if (this.loadedCode != null) { + this.loadedCode.clear(); + this.loadedCode = null; + } + + loadedClass = null; + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/MemoryClassCache.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/MemoryClassCache.java new file mode 100644 index 00000000000..faf58b3554a --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/MemoryClassCache.java @@ -0,0 +1,61 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.code; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class MemoryClassCache { + + private Map classMap = null; + + // singleton + private static class LazyHolder { + private static final MemoryClassCache INSTANCE = new MemoryClassCache(null); + } + + public static MemoryClassCache getInstance() { + return LazyHolder.INSTANCE; + } + + public MemoryClassCache(MemoryClassCache parent) { + this.classMap = new ConcurrentHashMap<>(); + } + + public MemoryClass getByClassName(String className) { + return classMap.get(className); + } + + public void put(MemoryClass mCls) { + classMap.put(mCls.getClassName(), mCls); + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/Signature.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/Signature.java new file mode 100644 index 00000000000..5359656b14b --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/Signature.java @@ -0,0 +1,82 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ +package com.cubrid.jsp.code; + +public class Signature { + private String className; + private String methodName; + private String args; + + public Signature(String cName, String mName, String args) { + className = cName; + methodName = mName; + this.args = args; + } + + public String getClassName() { + return className; + } + + public String getMethodName() { + return methodName; + } + + public String getArgs() { + return args; + } + + public static Signature parse(String signature) { + String className = null; + String methodName = null; + String args = null; + + int argStart = signature.indexOf('(') + 1; + if (argStart < 0) { + throw new IllegalArgumentException("Parenthesis '(' not found"); + } + int argEnd = signature.indexOf(')'); + if (argEnd < 0) { + throw new IllegalArgumentException("Parenthesis ')' not found"); + } + int nameStart = signature.substring(0, argStart).lastIndexOf('.') + 1; + + if (signature.charAt(0) == '\'') { + className = signature.substring(1, nameStart - 1); + } else { + className = signature.substring(0, nameStart - 1); + } + + methodName = signature.substring(nameStart, argStart - 1); + args = signature.substring(argStart, argEnd); + + return new Signature(className, methodName, args); + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/SourceCode.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/SourceCode.java new file mode 100644 index 00000000000..94f26e1f445 --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/code/SourceCode.java @@ -0,0 +1,61 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.code; + +import java.net.URI; +import javax.tools.SimpleJavaFileObject; + +public class SourceCode extends SimpleJavaFileObject { + private String className; + private String code; + + public SourceCode(String className, String code) { + super( + URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), + Kind.SOURCE); + this.code = code; + this.className = className; + } + + public String getClassName() { + return className; + } + + public String getCode() { + return code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return code; + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/compiler/MemoryFileManager.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/compiler/MemoryFileManager.java new file mode 100644 index 00000000000..16958507c47 --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/compiler/MemoryFileManager.java @@ -0,0 +1,79 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.compiler; + +import com.cubrid.jsp.code.CompiledCode; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; + +public class MemoryFileManager extends ForwardingJavaFileManager { + + private List codeList = new ArrayList(); + + protected MemoryFileManager(JavaFileManager fileManager) { + super(fileManager); + } + + @Override + public JavaFileObject getJavaFileForOutput( + JavaFileManager.Location location, + String className, + JavaFileObject.Kind kind, + FileObject sibling) + throws IOException { + try { + CompiledCode c = new CompiledCode(className); + + // register CompiledCode in GlobalClassStore + codeList.add(c); + + return c; + } catch (Exception e) { + throw new RuntimeException( + "Error occurs while creating output class file in memory for " + className, e); + } + } + + @Override + public ClassLoader getClassLoader(JavaFileManager.Location location) { + return null; + } + + public List getCodeList() { + return codeList; + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/compiler/MemoryJavaCompiler.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/compiler/MemoryJavaCompiler.java new file mode 100644 index 00000000000..4285cb62567 --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/compiler/MemoryJavaCompiler.java @@ -0,0 +1,103 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.compiler; + +import com.cubrid.jsp.Server; +import com.cubrid.jsp.code.CompiledCodeSet; +import com.cubrid.jsp.code.SourceCode; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.ToolProvider; + +public class MemoryJavaCompiler { + + private JavaCompiler compiler; + private List options = new ArrayList<>(); + + public MemoryJavaCompiler() { + compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + throw new IllegalStateException( + "Cannot find the system Java compiler. Check that your class path includes tools.jar"); + } + + Path cubrid_env_root = Server.getServer().getRootPath(); + useOptions("-encoding", Server.getConfig().getServerCharset().toString()); + useOptions("-classpath", cubrid_env_root + "/java/pl_server.jar"); + } + + public synchronized void useOptions(String... options) { + this.options.addAll(Arrays.asList(options)); + } + + public synchronized CompiledCodeSet compile(SourceCode code) { + DiagnosticCollector collector = new DiagnosticCollector<>(); + MemoryFileManager fileManager = + new MemoryFileManager(compiler.getStandardFileManager(null, null, null)); + JavaCompiler.CompilationTask task = + compiler.getTask(null, fileManager, collector, options, null, Arrays.asList(code)); + + boolean result = task.call(); + if (!result || collector.getDiagnostics().size() > 0) { + String exceptionMsg = new String("Unable to compile the source"); + boolean hasErrors = false; + + for (Diagnostic d : collector.getDiagnostics()) { + switch (d.getKind()) { + case NOTE: + case MANDATORY_WARNING: + case WARNING: + break; + case OTHER: + case ERROR: + default: + hasErrors = true; + break; + } + } + + if (hasErrors) { + throw new RuntimeException(exceptionMsg.toString()); + } + } + + assert (code.getClassName() != null); + + return new CompiledCodeSet(code.getClassName(), fileManager.getCodeList()); + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/context/Context.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/context/Context.java index 103e2821568..5082c747ac1 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/context/Context.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/context/Context.java @@ -32,13 +32,16 @@ package com.cubrid.jsp.context; import com.cubrid.jsp.ExecuteThread; +import com.cubrid.jsp.Server; import com.cubrid.jsp.TargetMethodCache; import com.cubrid.jsp.classloader.ClassLoaderManager; import com.cubrid.jsp.classloader.ContextClassLoader; +import com.cubrid.jsp.classloader.SessionClassLoaderManager; import com.cubrid.jsp.jdbc.CUBRIDServerSideConnection; import com.cubrid.jsp.protocol.Header; import com.cubrid.plcsql.builtin.MessageBuffer; import java.nio.ByteBuffer; +import java.nio.charset.Charset; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; @@ -55,7 +58,7 @@ public class Context { private int prevRequestId = 0; // charset - private String charSet = "UTF-8"; + private Charset sessionCharset = null; // single server-side connection per Context private CUBRIDServerSideConnection connection = null; @@ -66,7 +69,8 @@ public class Context { private Properties clientInfo = null; // dynamic classLoader for a session - private ContextClassLoader classLoader = null; + private SessionClassLoaderManager sessionClassLoaderManager = null; + private ContextClassLoader oldClassLoader = null; // file // method cache private TargetMethodCache methodCache = null; @@ -75,6 +79,7 @@ public class Context { private boolean transactionControl = false; // Connection Properties + private static Properties DEFAULT_CONNECTION_INFO = new Properties(); private Properties connectionInfo = null; // message buffer for DBMS_OUTPUT @@ -88,6 +93,10 @@ public long getSessionId() { return sessionId; } + public synchronized Connection getConnection() { + return getConnection(DEFAULT_CONNECTION_INFO); + } + public synchronized Connection getConnection(Properties prop) { if (this.connection == null) { this.connectionInfo = prop; @@ -116,8 +125,11 @@ public LinkedBlockingQueue getInboundQueue() { return inBound; } - public String getCharset() { - return charSet; + public Charset getSessionCharset() { + if (sessionCharset == null) { + sessionCharset = Server.getConfig().getServerCharset(); + } + return sessionCharset; } public void checkHeader(Header header) { @@ -132,20 +144,25 @@ public void checkHeader(Header header) { public void checkTranId(int tid) { if (tranactionId == -1) { tranactionId = tid; - classLoader = new ContextClassLoader(); + oldClassLoader = new ContextClassLoader(); } else if (tranactionId != tid) { // re-cretae dynamic class loader - if (classLoader - .getInitializedTime() - .compareTo( - ClassLoaderManager.getLastModifiedTimeOfPath( - ClassLoaderManager.getDynamicPath())) - != 0) { - classLoader = new ContextClassLoader(); + if (oldClassLoader != null + && oldClassLoader + .getInitializedTime() + .compareTo( + ClassLoaderManager.getLastModifiedTimeOfPath( + ClassLoaderManager.getDynamicPath())) + != 0) { + oldClassLoader = new ContextClassLoader(); methodCache.clear(); } clear(); tranactionId = tid; + + if (sessionClassLoaderManager != null) { + sessionClassLoaderManager.clear(); + } } } @@ -166,12 +183,20 @@ public MessageBuffer getMessageBuffer() { return messageBuffer; } - public ClassLoader getClassLoader() { - if (classLoader == null) { - classLoader = new ContextClassLoader(); + public SessionClassLoaderManager getSessionCLManager() { + if (sessionClassLoaderManager == null) { + sessionClassLoaderManager = new SessionClassLoaderManager(sessionId); } - return classLoader; + return sessionClassLoaderManager; + } + + public ClassLoader getOldClassLoader() { + if (oldClassLoader == null) { + oldClassLoader = new ContextClassLoader(); + } + + return oldClassLoader; } public TargetMethodCache getTargetMethodCache() { @@ -191,9 +216,11 @@ public boolean canTransactionControl() { return true; } - String tcProp = connectionInfo.getProperty("transaction_control"); - if (tcProp != null && "true".equalsIgnoreCase(tcProp)) { - return true; + if (connectionInfo != null) { + String tcProp = connectionInfo.getProperty("transaction_control"); + if (tcProp != null && "true".equalsIgnoreCase(tcProp)) { + return true; + } } return false; diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/AuthInfo.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/AuthInfo.java new file mode 100644 index 00000000000..57b20dcedbd --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/AuthInfo.java @@ -0,0 +1,51 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.data; + +import com.cubrid.jsp.protocol.PackableObject; + +public class AuthInfo implements PackableObject { + + public int command = -1; + public String authName = ""; + + public AuthInfo(int command, String authName) { + this.command = command; + this.authName = authName; + } + + @Override + public void pack(CUBRIDPacker packer) { + packer.packInt(command); + packer.packString(authName); + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CUBRIDPacker.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CUBRIDPacker.java index 8802374c73d..2077da81dd9 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CUBRIDPacker.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CUBRIDPacker.java @@ -31,14 +31,24 @@ package com.cubrid.jsp.data; +import com.cubrid.jsp.Server; +import com.cubrid.jsp.SysParam; +import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.jsp.jdbc.CUBRIDServerSideResultSet; import com.cubrid.jsp.protocol.PackableObject; +import com.cubrid.jsp.value.NullValue; +import com.cubrid.jsp.value.SetValue; +import com.cubrid.jsp.value.StringValue; +import com.cubrid.jsp.value.Value; import com.cubrid.plcsql.predefined.sp.SpLib; import cubrid.sql.CUBRIDOID; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.sql.Date; import java.sql.ResultSet; +import java.sql.Timestamp; import java.text.SimpleDateFormat; public class CUBRIDPacker { @@ -98,11 +108,12 @@ public void packDouble(double value) { } public void packString(String value) { - packCString(value.getBytes()); + Charset charset = Server.getConfig().getServerCharset(); + packCString(value.getBytes(charset)); } - public void packString(String value, String charset) throws UnsupportedEncodingException { - packCString(value.getBytes(charset)); + public void packString(String value, int codeset) throws UnsupportedEncodingException { + packCString(value.getBytes(SysParam.getCodesetString(codeset))); } public void packOID(SOID oid) { @@ -149,8 +160,134 @@ public void packPrimitiveBytes(ByteBuffer b) { buffer.put(b.array(), 0, b.position()); } - // TODO: legacy implementation, this function will be modified - public void packValue(Object result, int ret_type, String charset) + public void packValue(Value value, int dbType) + throws UnsupportedEncodingException, TypeMismatchException { + if (value == null || value instanceof NullValue) { + dbType = DBType.DB_NULL; + } + + switch (dbType) { + case DBType.DB_INT: + packInt(dbType); + packInt(value.toInt()); + break; + case DBType.DB_SHORT: + packInt(dbType); + packShort(value.toShort()); + break; + case DBType.DB_BIGINT: + packInt(dbType); + packBigInt(value.toLong()); + break; + case DBType.DB_FLOAT: + packInt(dbType); + packFloat(value.toFloat()); + break; + case DBType.DB_DOUBLE: + case DBType.DB_MONETARY: + packInt(dbType); + packDouble(value.toDouble()); + break; + + case DBType.DB_CHAR: + case DBType.DB_STRING: + packInt(dbType); + if (value instanceof StringValue) { + packInt(value.getCodeSet()); + packCString(value.toByteArray()); + } else { + packInt(value.getCodeSet()); + packString(value.toString(), value.getCodeSet()); + } + break; + + case DBType.DB_NUMERIC: + packInt(dbType); + packString(value.toBigDecimal().toPlainString()); + break; + + case DBType.DB_DATE: + packInt(dbType); + Date d = value.toDate(); + if (d.equals(SpLib.ZERO_DATE)) { + packString("0000-00-00"); + } else { + packString(d.toString()); + } + break; + case DBType.DB_TIME: + packInt(dbType); + packString(value.toTime().toString()); + break; + + case DBType.DB_TIMESTAMP: + case DBType.DB_DATETIME: + packInt(dbType); + + Timestamp ts = null; + if (dbType == DBType.DB_DATETIME) { + ts = value.toDatetime(); + if (ts.equals(SpLib.ZERO_DATETIME)) { + packString("0000-00-00 00:00:00.000"); + } else { + packString(ts.toString()); + } + } else { + ts = value.toTimestamp(); + if (SpLib.isZeroTimestamp((java.sql.Timestamp) ts)) { + packString("0000-00-00 00:00:00"); + } else { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + packString(formatter.format(ts)); + } + } + break; + + case DBType.DB_OID: + case DBType.DB_OBJECT: + packInt(dbType); + byte[] oid = value.toOid().getOID(); + packOID(new SOID(oid)); + break; + + case DBType.DB_SET: + case DBType.DB_MULTISET: + case DBType.DB_SEQUENCE: + packInt(dbType); + + Object[] values = null; + if (value instanceof SetValue) { + values = (Value[]) ((SetValue) value).toValueArray(); + if (values != null) { + packInt(values.length); + for (int i = 0; i < values.length; i++) { + int dt = DBType.DB_NULL; + if (values[i] != null) { + dt = ((Value) values[i]).getDbType(); + } + packValue((Value) values[i], dt); + } + } + } + + if (values == null) { + values = value.toObjectArray(); + packObject(values, dbType, value.getCodeSet()); + } + break; + + case DBType.DB_RESULTSET: + packInt(dbType); + packBigInt(value.toLong()); + break; + + default: + packInt(DBType.DB_NULL); + break; + } + } + + public void packObject(Object result, int ret_type, int codeset) throws UnsupportedEncodingException { if (result == null) { packInt(DBType.DB_NULL); @@ -167,24 +304,25 @@ public void packValue(Object result, int ret_type, String charset) packInt(DBType.DB_FLOAT); packFloat(((Float) result).floatValue()); } else if (result instanceof Double) { - packInt(ret_type); + packInt(DBType.DB_DOUBLE); packDouble(((Double) result).doubleValue()); } else if (result instanceof BigDecimal) { packInt(DBType.DB_NUMERIC); - packString(((BigDecimal) result).toPlainString(), charset); + packString(((BigDecimal) result).toPlainString(), codeset); } else if (result instanceof String) { packInt(DBType.DB_STRING); - packString((String) result, charset); + packInt(codeset); + packString((String) result, codeset); } else if (result instanceof java.sql.Date) { packInt(DBType.DB_DATE); if (result.equals(SpLib.ZERO_DATE)) { - packString("0000-00-00", charset); + packString("0000-00-00", codeset); } else { - packString(result.toString(), charset); + packString(result.toString(), codeset); } } else if (result instanceof java.sql.Time) { packInt(DBType.DB_TIME); - packString(result.toString(), charset); + packString(result.toString(), codeset); } else if (result instanceof java.sql.Timestamp) { packInt(ret_type); if (ret_type == DBType.DB_DATETIME) { @@ -216,16 +354,15 @@ public void packValue(Object result, int ret_type, String charset) packInt(array.length); for (int i = 0; i < array.length; i++) { array[i] = new Integer(((int[]) result)[i]); - packValue(array[i], ret_type, charset); + packObject(array[i], DBType.DB_INT, codeset); } - packValue(array, ret_type, charset); } else if (result instanceof short[]) { int length = ((short[]) result).length; Short[] array = new Short[length]; packInt(array.length); for (int i = 0; i < array.length; i++) { array[i] = new Short(((short[]) result)[i]); - packValue(array, ret_type, charset); + packObject(array, DBType.DB_SHORT, codeset); } } else if (result instanceof float[]) { int length = ((float[]) result).length; @@ -233,7 +370,7 @@ public void packValue(Object result, int ret_type, String charset) packInt(array.length); for (int i = 0; i < array.length; i++) { array[i] = new Float(((float[]) result)[i]); - packValue(array[i], ret_type, charset); + packObject(array[i], DBType.DB_FLOAT, codeset); } } else if (result instanceof double[]) { int length = ((double[]) result).length; @@ -241,7 +378,7 @@ public void packValue(Object result, int ret_type, String charset) packInt(array.length); for (int i = 0; i < array.length; i++) { array[i] = new Double(((double[]) result)[i]); - packValue(array[i], ret_type, charset); + packObject(array[i], DBType.DB_DOUBLE, codeset); } } else if (result instanceof Object[]) { packInt(ret_type); @@ -249,7 +386,7 @@ public void packValue(Object result, int ret_type, String charset) packInt(arr.length); for (int i = 0; i < arr.length; i++) { - packValue(arr[i], ret_type, charset); + packObject(arr[i], ret_type, codeset); } } else { // FIXME: treat as NULL diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CUBRIDUnpacker.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CUBRIDUnpacker.java index 27e3d03f36a..54f59479067 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CUBRIDUnpacker.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CUBRIDUnpacker.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.data; +import com.cubrid.jsp.Server; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.jsp.value.*; import java.nio.ByteBuffer; @@ -105,7 +106,7 @@ public String unpackCString() { byte[] str = new byte[len]; buffer.get(str); align(DataUtilities.INT_ALIGNMENT); - return new String(str); + return new String(str, Server.getConfig().getServerCharset()); } else { align(DataUtilities.INT_ALIGNMENT); return ""; @@ -114,9 +115,15 @@ public String unpackCString() { public byte[] unpackCStringByteArray() { int len = unpackStringSize(); - byte[] str = new byte[len]; - buffer.get(str); - return str; + if (len > 0) { + byte[] str = new byte[len]; + buffer.get(str); + align(DataUtilities.INT_ALIGNMENT); + return str; + } else { + align(DataUtilities.INT_ALIGNMENT); + return new byte[0]; + } } public int unpackStringSize() { @@ -181,7 +188,8 @@ public Value unpackValue(int paramType) throws TypeMismatchException { break; case DBType.DB_CHAR: case DBType.DB_STRING: - arg = new StringValue(unpackCString()); + int codeset = unpackInt(); + arg = new StringValue(unpackCStringByteArray(), codeset); break; case DBType.DB_DATE: { @@ -244,7 +252,7 @@ public Value unpackValue(int paramType) throws TypeMismatchException { case DBType.DB_OID: case DBType.DB_OBJECT: { - SOID soid = new SOID(this); + SOID soid = unpackOID(); arg = new OidValue(soid); } break; @@ -258,113 +266,11 @@ public Value unpackValue(int paramType) throws TypeMismatchException { return arg; } - public Value unpackValue(int paramType, int mode, int dbType) throws TypeMismatchException { - Value arg = null; - switch (paramType) { - case DBType.DB_SHORT: - arg = new ShortValue(unpackShort(), mode, dbType); - break; - case DBType.DB_INT: - arg = new IntValue(unpackInt(), mode, dbType); - break; - case DBType.DB_BIGINT: - arg = new LongValue(unpackBigint(), mode, dbType); - break; - case DBType.DB_FLOAT: - arg = new FloatValue(unpackFloat(), mode, dbType); - break; - case DBType.DB_DOUBLE: - case DBType.DB_MONETARY: - arg = new DoubleValue(unpackDouble(), mode, dbType); - break; - case DBType.DB_NUMERIC: - arg = new NumericValue(unpackCString(), mode, dbType); - break; - case DBType.DB_CHAR: - case DBType.DB_STRING: - arg = new StringValue(unpackCString(), mode, dbType); - break; - case DBType.DB_DATE: - { - int year = unpackInt(); - int month = unpackInt(); - int day = unpackInt(); - - arg = new DateValue(year, month, day, mode, dbType); - } - break; - case DBType.DB_TIME: - { - int hour = unpackInt(); - int min = unpackInt(); - int sec = unpackInt(); - - Calendar cal = Calendar.getInstance(); - cal.set(0, 0, 0, hour, min, sec); - - arg = new TimeValue(hour, min, sec, mode, dbType); - } - break; - case DBType.DB_TIMESTAMP: - { - int year = unpackInt(); - int month = unpackInt(); - int day = unpackInt(); - int hour = unpackInt(); - int min = unpackInt(); - int sec = unpackInt(); - arg = new TimestampValue(year, month, day, hour, min, sec, mode, dbType); - } - break; - case DBType.DB_DATETIME: - { - int year = unpackInt(); - int month = unpackInt(); - int day = unpackInt(); - int hour = unpackInt(); - int min = unpackInt(); - int sec = unpackInt(); - int msec = unpackInt(); - arg = new DatetimeValue(year, month, day, hour, min, sec, msec, mode, dbType); - } - break; - case DBType.DB_SET: - case DBType.DB_MULTISET: - case DBType.DB_SEQUENCE: - { - int nCol = unpackInt(); - arg = new SetValue(unpackSetValue(nCol), mode, dbType); - } - break; - case DBType.DB_OID: - case DBType.DB_OBJECT: - { - SOID oid = new SOID(this); - arg = new OidValue(oid, mode, dbType); - } - break; - case DBType.DB_RESULTSET: - { - long queryId = unpackBigint(); - arg = new ResultSetValue(queryId); - } - break; - case DBType.DB_NULL: - arg = new NullValue(mode, dbType); - break; - default: - // unknown type - break; - } - return arg; - } - private Value[] unpackSetValue(int paramCount) throws TypeMismatchException { Value[] args = new Value[paramCount]; for (int i = 0; i < paramCount; i++) { int paramType = unpackInt(); - // FIXME: dbType=0 is dummy, it is from legacy code. I'm not sure about it - Value arg = unpackValue(paramType, Value.IN, 0); + Value arg = unpackValue(paramType); args[i] = (arg); } return args; diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CompileInfo.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CompileInfo.java index b09e349f862..b68aa3c3251 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CompileInfo.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CompileInfo.java @@ -44,6 +44,9 @@ public class CompileInfo implements PackableObject { public String className = null; public String signature = null; + public int compiledType = -1; + public byte[] compiledCode = null; + public CompileInfo(int code, int line, int column, String msg) { assert code < 0; @@ -73,6 +76,11 @@ public void pack(CUBRIDPacker packer) { packer.packString(createStmt); packer.packString(className); packer.packString(signature); + + packer.packInt(compiledType); + if (compiledType >= 0) { + packer.packCString(compiledCode); + } } } } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CompileRequest.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CompileRequest.java new file mode 100644 index 00000000000..29a80f2a1ab --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/data/CompileRequest.java @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2016 CUBRID Corporation. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +package com.cubrid.jsp.data; + +public class CompileRequest { + public String code = null; + public String owner = null; + public String mode = null; + + public CompileRequest(CUBRIDUnpacker unpacker) { + code = unpacker.unpackCString(); + owner = unpacker.unpackCString(); + mode = unpacker.unpackCString(); + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/impl/SUBindParameter.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/impl/SUBindParameter.java index cc609baa7b5..f911ac3f29e 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/impl/SUBindParameter.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/impl/SUBindParameter.java @@ -30,7 +30,7 @@ */ package com.cubrid.jsp.impl; -import com.cubrid.jsp.ExecuteThread; +import com.cubrid.jsp.Server; import com.cubrid.jsp.data.CUBRIDPacker; import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.jdbc.CUBRIDServerSideJDBCErrorCode; @@ -108,7 +108,7 @@ synchronized void pack(CUBRIDPacker packer) throws UnsupportedEncodingException int cnt = paramMode.length; packer.packInt(cnt); for (int i = 0; i < cnt; i++) { - packer.packValue(values[i], types[i], ExecuteThread.charSet); + packer.packObject(values[i], types[i], Server.getConfig().getServerCodesetId()); packer.packInt((int) paramMode[i]); } } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/impl/SUConnection.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/impl/SUConnection.java index 36c8fdbe6f0..6b5bc99d2f2 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/impl/SUConnection.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/impl/SUConnection.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.impl; +import com.cubrid.jsp.Server; import com.cubrid.jsp.context.Context; import com.cubrid.jsp.data.CUBRIDPacker; import com.cubrid.jsp.data.CUBRIDUnpacker; @@ -264,7 +265,7 @@ public void putByOID(CUBRIDOID oid, String[] attributeName, Object values[]) } int type = DBType.getObjectDBtype(values[i]); - packer.packValue(values[i], type, "UTF-8"); + packer.packObject(values[i], type, Server.getConfig().getServerCodesetId()); } } else { packer.packInt(0); @@ -313,7 +314,7 @@ protected CUBRIDUnpacker collectionCmd( if (value != null) { packer.packInt(1); // has value int type = DBType.getObjectDBtype(value); - packer.packValue(value, type, "UTF-8"); + packer.packObject(value, type, Server.getConfig().getServerCodesetId()); } else { packer.packInt(0); // has value } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/BootstrapRequest.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/BootstrapRequest.java new file mode 100644 index 00000000000..683fd3115e2 --- /dev/null +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/BootstrapRequest.java @@ -0,0 +1,31 @@ +package com.cubrid.jsp.protocol; + +import com.cubrid.jsp.SysParam; +import com.cubrid.jsp.data.CUBRIDUnpacker; + +public class BootstrapRequest implements UnPackableObject { + + private SysParam[] sysParam; + + public BootstrapRequest(CUBRIDUnpacker unpacker) { + unpack(unpacker); + } + + @Override + public void unpack(CUBRIDUnpacker unpacker) { + int size = unpacker.unpackInt(); + sysParam = new SysParam[size]; + + try { + for (int i = 0; i < size; i++) { + sysParam[i] = new SysParam(unpacker); + } + } catch (Exception e) { + // do nothing + } + } + + public SysParam[] getSystemParameters() { + return sysParam; + } +} diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/PrepareArgs.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/PrepareArgs.java index d52e29d7270..cd723d5ce7d 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/PrepareArgs.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/PrepareArgs.java @@ -24,7 +24,7 @@ public Value[] getArgs() { public int getArgCount() { if (arguments == null) { - return -1; + return 0; } else { return arguments.length; } @@ -39,15 +39,16 @@ public void readArgs(CUBRIDUnpacker unpacker) throws TypeMismatchException { tranId = unpacker.unpackInt(); int argCount = unpacker.unpackInt(); - if (arguments == null || argCount != arguments.length) { + if (argCount > 0) { arguments = new Value[argCount]; - } - - for (int i = 0; i < arguments.length; i++) { - int paramType = unpacker.unpackInt(); + for (int i = 0; i < arguments.length; i++) { + int paramType = unpacker.unpackInt(); - Value arg = unpacker.unpackValue(paramType); - arguments[i] = (arg); + Value arg = unpacker.unpackValue(paramType); + arguments[i] = (arg); + } + } else { + arguments = null; } } } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/RequestCode.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/RequestCode.java index 59fc505d7bc..fa0c182ea80 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/RequestCode.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/protocol/RequestCode.java @@ -17,6 +17,10 @@ public class RequestCode { public static final int REQUEST_GLOBAL_SEMANTICS = 0xA1; public static final int REQUEST_BUILTIN_FUNCTION = 0xA4; + public static final int REQUEST_CHANGE_AUTH_RIGHTS = 0xC8; + public static final int REQUEST_CODE_ATTR = 0xC9; + + public static final int UTIL_BOOTSTRAP = 0xDD; public static final int UTIL_PING = 0xDE; public static final int UTIL_STATUS = 0xEE; public static final int UTIL_TERMINATE_THREAD = 0xFE; diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/BooleanValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/BooleanValue.java index fce60cfda75..7b6bbe047dc 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/BooleanValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/BooleanValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; public class BooleanValue extends Value { @@ -46,13 +47,7 @@ public BooleanValue(boolean b) { if (b) { value = 1; } - } - - public BooleanValue(boolean b, int mode) { - super(mode); - if (b) { - value = 1; - } + this.dbType = DBType.DB_INT; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ByteValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ByteValue.java index 070f2279da2..2f5d00c79c7 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ByteValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ByteValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import java.math.BigDecimal; @@ -45,11 +46,7 @@ protected String getTypeName() { public ByteValue(byte value) { super(); this.value = value; - } - - public ByteValue(byte value, int mode) { - super(mode); - this.value = value; + this.dbType = DBType.DB_CHAR; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DateTimeParser.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DateTimeParser.java index 7aff87659a4..1c680bb7f88 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DateTimeParser.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DateTimeParser.java @@ -38,6 +38,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.Arrays; @@ -150,12 +151,12 @@ public static ZonedDateTime parseZonedDateAndTime(String s, boolean forDatetime) // get timezone offset LocalDateTime localPart; - ZoneOffset zone; + ZoneId zone; int delim = s.lastIndexOf(" "); if (delim < 0) { // no timezone offset localPart = parseLocalDateAndTime(s, forDatetime); - zone = Server.getSystemParameterTimezone(Server.SYS_PARAM_TIMEZONE); + zone = Server.getConfig().getTimeZone(); } else { String dt = s.substring(0, delim); String z = s.substring(delim + 1); @@ -165,7 +166,7 @@ public static ZonedDateTime parseZonedDateAndTime(String s, boolean forDatetime) } catch (DateTimeException e) { // z turn out not to be a timezone offset. try timezone omitted string localPart = parseLocalDateAndTime(s, forDatetime); - zone = Server.getSystemParameterTimezone(Server.SYS_PARAM_TIMEZONE); + zone = Server.getConfig().getTimeZone(); } } @@ -270,7 +271,7 @@ private static LocalDateTime parseLocalDateAndTime(String s, boolean millis) { } private static int getCurrentYear() { - ZoneOffset timezone = Server.getSystemParameterTimezone(Server.SYS_PARAM_TIMEZONE); + ZoneId timezone = Server.getConfig().getTimeZone(); return ZonedDateTime.now(timezone).getYear(); } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DateValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DateValue.java index 3c9a87e96a4..52ea89580d3 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DateValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DateValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.sql.Date; @@ -55,20 +56,7 @@ public DateValue(int year, int mon, int day) throws TypeMismatchException { if (!SpLib.checkDate(date)) { throw new TypeMismatchException("invalid Date " + date); } - } - - public DateValue(int year, int mon, int day, int mode, int dbType) - throws TypeMismatchException { - super(mode); - Calendar cal = Calendar.getInstance(); - cal.set(year, mon, day, 0, 0, 0); - cal.set(Calendar.MILLISECOND, 0); - - date = new Date(cal.getTimeInMillis()); - if (!SpLib.checkDate(date)) { - throw new TypeMismatchException("invalid Date " + date); - } - this.dbType = dbType; + this.dbType = DBType.DB_DATE; } public DateValue(Date date) throws TypeMismatchException { @@ -76,6 +64,7 @@ public DateValue(Date date) throws TypeMismatchException { throw new TypeMismatchException("invalid Date " + date); } this.date = date; + this.dbType = DBType.DB_DATE; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DatetimeValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DatetimeValue.java index e90af1aaf0a..8cb88b49bf0 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DatetimeValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DatetimeValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.sql.Date; @@ -55,32 +56,18 @@ public DatetimeValue(int year, int mon, int day, int hour, int min, int sec, int c.set(Calendar.MILLISECOND, msec); timestamp = new Timestamp(c.getTimeInMillis()); + this.dbType = DBType.DB_DATETIME; if (!SpLib.checkDatetime(timestamp)) { throw new TypeMismatchException("invalid Datetime " + timestamp); } } - public DatetimeValue( - int year, int mon, int day, int hour, int min, int sec, int msec, int mode, int dbType) - throws TypeMismatchException { - super(mode); - - Calendar c = Calendar.getInstance(); - c.set(year, mon, day, hour, min, sec); - c.set(Calendar.MILLISECOND, msec); - - timestamp = new Timestamp(c.getTimeInMillis()); - if (!SpLib.checkDatetime(timestamp)) { - throw new TypeMismatchException("invalid Datetime " + timestamp); - } - this.dbType = dbType; - } - public DatetimeValue(Timestamp timestamp) throws TypeMismatchException { if (timestamp != null && !SpLib.checkDatetime(timestamp)) { throw new TypeMismatchException("invalid Datetime " + timestamp); } this.timestamp = timestamp; + this.dbType = DBType.DB_DATETIME; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DoubleValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DoubleValue.java index 95814c87849..225a599b6c4 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DoubleValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/DoubleValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.math.BigDecimal; @@ -51,15 +52,7 @@ public DoubleValue(double value) throws TypeMismatchException { throw new TypeMismatchException("invalid double " + value); } this.value = value; - } - - public DoubleValue(double value, int mode, int dbType) throws TypeMismatchException { - super(mode); - if (!Double.isFinite(value)) { - throw new TypeMismatchException("invalid double " + value); - } - this.value = value; - this.dbType = dbType; + this.dbType = DBType.DB_DOUBLE; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/FloatValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/FloatValue.java index 3aec4f44a10..832131cac1d 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/FloatValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/FloatValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.math.BigDecimal; @@ -51,15 +52,7 @@ public FloatValue(float value) throws TypeMismatchException { throw new TypeMismatchException("invalid float " + value); } this.value = value; - } - - public FloatValue(float value, int mode, int dbType) throws TypeMismatchException { - super(mode); - if (!Float.isFinite(value)) { - throw new TypeMismatchException("invalid float " + value); - } - this.value = value; - this.dbType = dbType; + this.dbType = DBType.DB_FLOAT; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/IntValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/IntValue.java index 2e0f3187c57..86b854144ce 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/IntValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/IntValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.math.BigDecimal; @@ -48,12 +49,7 @@ protected String getTypeName() { public IntValue(int value) { super(); this.value = value; - } - - public IntValue(int value, int mode, int dbType) { - super(mode); - this.value = value; - this.dbType = dbType; + this.dbType = DBType.DB_INT; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/LongValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/LongValue.java index bbc4a22709a..35c531bbbcc 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/LongValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/LongValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.math.BigDecimal; @@ -48,12 +49,7 @@ protected String getTypeName() { public LongValue(long value) { super(); this.value = value; - } - - public LongValue(long value, int mode, int dbType) { - super(mode); - this.value = value; - this.dbType = dbType; + this.dbType = DBType.DB_BIGINT; } @Override @@ -68,7 +64,7 @@ public short toShort() throws TypeMismatchException { @Override public int toInt() throws TypeMismatchException { - return SpLib.convBigintToShort(value); + return SpLib.convBigintToInt(value); } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/NullValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/NullValue.java index febe6e9c1e1..7dae72c0e6e 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/NullValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/NullValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.jsp.impl.SUConnection; import cubrid.sql.CUBRIDOID; @@ -48,11 +49,7 @@ protected String getTypeName() { public NullValue() { super(); - } - - public NullValue(int mode, int dbType) { - super(mode); - this.dbType = dbType; + this.dbType = DBType.DB_NULL; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/NumericValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/NumericValue.java index d9ac6974e72..68f70820a83 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/NumericValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/NumericValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.math.BigDecimal; @@ -47,6 +48,7 @@ protected String getTypeName() { public NumericValue(String value) { super(); this.value = SpLib.convStringToNumeric(value); + this.dbType = DBType.DB_NUMERIC; } public NumericValue(BigDecimal value) throws TypeMismatchException { @@ -55,12 +57,7 @@ public NumericValue(BigDecimal value) throws TypeMismatchException { throw new TypeMismatchException("precision exceeds 38: " + value); } this.value = value; - } - - public NumericValue(String value, int mode, int dbType) { - super(mode); - this.value = SpLib.convStringToNumeric(value); - this.dbType = dbType; + this.dbType = DBType.DB_NUMERIC; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/OidValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/OidValue.java index 2cee5248594..60e51b6e131 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/OidValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/OidValue.java @@ -32,6 +32,7 @@ package com.cubrid.jsp.value; import com.cubrid.jsp.Server; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.data.SOID; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.jsp.jdbc.CUBRIDServerSideConnection; @@ -51,26 +52,14 @@ protected String getTypeName() { public OidValue(SOID oid) { oidValue = oid; + this.dbType = DBType.DB_OID; } public OidValue(CUBRIDOID oid) { byte[] bOid = oid.getOID(); oidValue = new SOID(bOid); this.oidObject = oid; - } - - public OidValue(SOID oid, int mode, int dbType) { - super(mode); - this.oidValue = oid; - this.dbType = dbType; - } - - public OidValue(CUBRIDOID oid, int mode, int dbType) { - super(mode); - this.oidObject = oid; - byte[] bOid = oid.getOID(); - oidValue = new SOID(bOid); - this.dbType = dbType; + this.dbType = DBType.DB_OID; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ResultSetValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ResultSetValue.java index 04f048d6cf0..4582b54c0a7 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ResultSetValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ResultSetValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.impl.SUConnection; import com.cubrid.jsp.jdbc.CUBRIDServerSideOutResultSet; import com.cubrid.jsp.jdbc.CUBRIDServerSideResultSet; @@ -48,12 +49,14 @@ protected String getTypeName() { public ResultSetValue(long queryId) { super(); this.queryId = queryId; + this.dbType = DBType.DB_RESULTSET; } public ResultSetValue(ResultSet rset) { super(); this.rset = rset; this.queryId = ((CUBRIDServerSideResultSet) rset).getQueryId(); + this.dbType = DBType.DB_RESULTSET; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/SetValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/SetValue.java index 15050272d90..0db8940b63b 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/SetValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/SetValue.java @@ -31,6 +31,8 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; +import com.cubrid.jsp.exception.ExecuteException; import com.cubrid.jsp.exception.TypeMismatchException; import cubrid.sql.CUBRIDOID; import java.math.BigDecimal; @@ -44,72 +46,92 @@ protected String getTypeName() { return TYPE_NAME_SET; } - private Object[] values; + private Value[] values; + private Object[] objects; public SetValue(Value[] args) throws TypeMismatchException { super(); - values = toObjectArray(args); - } - - public SetValue(Value[] args, int mode, int dbType) throws TypeMismatchException { - super(mode); - values = toObjectArray(args); - this.dbType = dbType; - } - - public SetValue(Object[] objects) { - this.values = objects; + this.values = args; + this.objects = toJavaObjectArray(args); + this.dbType = DBType.DB_SET; + } + + public SetValue(Object[] objects) throws TypeMismatchException { + this.objects = objects; + setValuesFromObjects(); + } + + private void setValuesFromObjects() throws TypeMismatchException { + if (objects != null) { + this.values = new Value[objects.length]; + for (int i = 0; i < objects.length; i++) { + try { + this.values[i] = ValueUtilities.createValueFrom(objects[i]); + } catch (ExecuteException e) { + this.values[i] = new NullValue(); + assert false; // This should never happen + } + } + } + this.dbType = DBType.DB_SET; } - public SetValue(byte[] objects) { + public SetValue(byte[] objects) throws TypeMismatchException { Object[] array = new Object[objects.length]; for (int i = 0; i < objects.length; i++) { array[i] = new Byte(objects[i]); } - this.values = array; + this.objects = array; + this.dbType = DBType.DB_SET; + setValuesFromObjects(); } - public SetValue(short[] objects) { + public SetValue(short[] objects) throws TypeMismatchException { Object[] array = new Object[objects.length]; for (int i = 0; i < objects.length; i++) { array[i] = new Short(objects[i]); } - this.values = array; + this.objects = array; + setValuesFromObjects(); } - public SetValue(int[] objects) { + public SetValue(int[] objects) throws TypeMismatchException { Object[] array = new Object[objects.length]; for (int i = 0; i < objects.length; i++) { array[i] = new Integer(objects[i]); } - this.values = array; + this.objects = array; + setValuesFromObjects(); } - public SetValue(long[] objects) { + public SetValue(long[] objects) throws TypeMismatchException { Object[] array = new Object[objects.length]; for (int i = 0; i < objects.length; i++) { array[i] = new Long(objects[i]); } - this.values = array; + this.objects = array; + setValuesFromObjects(); } - public SetValue(float[] objects) { + public SetValue(float[] objects) throws TypeMismatchException { Object[] array = new Object[objects.length]; for (int i = 0; i < objects.length; i++) { array[i] = new Float(objects[i]); } - this.values = array; + this.objects = array; + setValuesFromObjects(); } - public SetValue(double[] objects) { + public SetValue(double[] objects) throws TypeMismatchException { Object[] array = new Object[objects.length]; for (int i = 0; i < objects.length; i++) { array[i] = new Double(objects[i]); } - this.values = array; + this.objects = array; + setValuesFromObjects(); } - private Object[] toObjectArray(Value[] args) throws TypeMismatchException { + private Object[] toJavaObjectArray(Value[] args) throws TypeMismatchException { Object[] array = new Object[args.length]; for (int i = 0; i < args.length; i++) { @@ -118,14 +140,18 @@ private Object[] toObjectArray(Value[] args) throws TypeMismatchException { return array; } + public Value[] toValueArray() throws TypeMismatchException { + return values; + } + @Override public Object[] toObjectArray() throws TypeMismatchException { - return values; + return objects; } @Override public Object toObject() throws TypeMismatchException { - return values; + return objects; } @Override @@ -133,13 +159,13 @@ public String toString() { StringBuffer buf = new StringBuffer(); buf.append("{"); - for (int i = 0; i < values.length; i++) { - if (values[i] == null) { + for (int i = 0; i < objects.length; i++) { + if (objects[i] == null) { buf.append("null"); } else { - buf.append(values[i].toString()); + buf.append(objects[i].toString()); } - if (i < values.length - 1) { + if (i < objects.length - 1) { buf.append(", "); } } @@ -149,190 +175,190 @@ public String toString() { @Override public byte[] toByteArray() throws TypeMismatchException { - byte[] array = new byte[values.length]; + byte[] array = new byte[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = ((Byte) values[i]).byteValue(); + for (int i = 0; i < objects.length; i++) { + array[i] = ((Byte) objects[i]).byteValue(); } return array; } @Override public short[] toShortArray() throws TypeMismatchException { - short[] array = new short[values.length]; + short[] array = new short[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = ((Short) values[i]).shortValue(); + for (int i = 0; i < objects.length; i++) { + array[i] = ((Short) objects[i]).shortValue(); } return array; } @Override public int[] toIntegerArray() throws TypeMismatchException { - int[] array = new int[values.length]; + int[] array = new int[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = ((Integer) values[i]).intValue(); + for (int i = 0; i < objects.length; i++) { + array[i] = ((Integer) objects[i]).intValue(); } return array; } @Override public long[] toLongArray() throws TypeMismatchException { - long[] array = new long[values.length]; + long[] array = new long[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = ((Long) values[i]).longValue(); + for (int i = 0; i < objects.length; i++) { + array[i] = ((Long) objects[i]).longValue(); } return array; } @Override public float[] toFloatArray() throws TypeMismatchException { - float[] array = new float[values.length]; + float[] array = new float[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = ((Float) values[i]).floatValue(); + for (int i = 0; i < objects.length; i++) { + array[i] = ((Float) objects[i]).floatValue(); } return array; } @Override public double[] toDoubleArray() throws TypeMismatchException { - double[] array = new double[values.length]; + double[] array = new double[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = ((Double) values[i]).doubleValue(); + for (int i = 0; i < objects.length; i++) { + array[i] = ((Double) objects[i]).doubleValue(); } return array; } @Override public BigDecimal[] toBigDecimalArray() throws TypeMismatchException { - BigDecimal[] array = new BigDecimal[values.length]; + BigDecimal[] array = new BigDecimal[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (BigDecimal) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (BigDecimal) objects[i]; } return array; } @Override public Date[] toDateArray() throws TypeMismatchException { - Date[] array = new Date[values.length]; + Date[] array = new Date[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Date) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Date) objects[i]; } return array; } @Override public Time[] toTimeArray() throws TypeMismatchException { - Time[] array = new Time[values.length]; + Time[] array = new Time[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Time) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Time) objects[i]; } return array; } @Override public Timestamp[] toTimestampArray() throws TypeMismatchException { - Timestamp[] array = new Timestamp[values.length]; + Timestamp[] array = new Timestamp[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Timestamp) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Timestamp) objects[i]; } return array; } @Override public Timestamp[] toDatetimeArray() throws TypeMismatchException { - Timestamp[] array = new Timestamp[values.length]; + Timestamp[] array = new Timestamp[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Timestamp) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Timestamp) objects[i]; } return array; } @Override public String[] toStringArray() throws TypeMismatchException { - String[] array = new String[values.length]; + String[] array = new String[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (String) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (String) objects[i]; } return array; } @Override public Byte[] toByteObjArray() throws TypeMismatchException { - Byte[] array = new Byte[values.length]; + Byte[] array = new Byte[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Byte) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Byte) objects[i]; } return array; } @Override public Double[] toDoubleObjArray() throws TypeMismatchException { - Double[] array = new Double[values.length]; + Double[] array = new Double[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Double) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Double) objects[i]; } return array; } @Override public Float[] toFloatObjArray() throws TypeMismatchException { - Float[] array = new Float[values.length]; + Float[] array = new Float[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Float) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Float) objects[i]; } return array; } @Override public Integer[] toIntegerObjArray() throws TypeMismatchException { - Integer[] array = new Integer[values.length]; + Integer[] array = new Integer[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Integer) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Integer) objects[i]; } return array; } @Override public Long[] toLongObjArray() throws TypeMismatchException { - Long[] array = new Long[values.length]; + Long[] array = new Long[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Long) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Long) objects[i]; } return array; } @Override public Short[] toShortObjArray() throws TypeMismatchException { - Short[] array = new Short[values.length]; + Short[] array = new Short[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (Short) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (Short) objects[i]; } return array; } @Override public CUBRIDOID[] toOidArray() throws TypeMismatchException { - CUBRIDOID[] array = new CUBRIDOID[values.length]; + CUBRIDOID[] array = new CUBRIDOID[objects.length]; - for (int i = 0; i < values.length; i++) { - array[i] = (CUBRIDOID) values[i]; + for (int i = 0; i < objects.length; i++) { + array[i] = (CUBRIDOID) objects[i]; } return array; } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ShortValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ShortValue.java index 5e3a5cb55a0..dcc8de8df40 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ShortValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ShortValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.math.BigDecimal; @@ -48,12 +49,7 @@ protected String getTypeName() { public ShortValue(short value) { super(); this.value = value; - } - - public ShortValue(short value, int mode, int dbType) { - super(mode); - this.value = value; - this.dbType = dbType; + this.dbType = DBType.DB_SHORT; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/StringValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/StringValue.java index cc29c39221f..7e553de1450 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/StringValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/StringValue.java @@ -31,8 +31,12 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.Server; +import com.cubrid.jsp.SysParam; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; +import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.sql.Date; import java.sql.Time; @@ -44,111 +48,129 @@ protected String getTypeName() { return TYPE_NAME_STRING; } - private String value; + private byte[] primitiveValue; - public StringValue(String value) { + public StringValue(byte[] value, int codeset) { super(); - this.value = value; + this.primitiveValue = value; + this.codeset = codeset; + this.resolved = null; + this.dbType = DBType.DB_STRING; + } + + public StringValue(byte[] value) { + this(value, Server.getConfig().getServerCodesetId()); } - public StringValue(String value, int mode, int dbType) { - super(mode); - this.value = value; - this.dbType = dbType; + public StringValue(String value) { + this(value.getBytes(Server.getConfig().getServerCharset())); } @Override public byte toByte() throws TypeMismatchException { - return SpLib.convStringToByte(value); + return SpLib.convStringToByte(toString()); + } + + @Override + public byte[] toByteArray() throws TypeMismatchException { + return primitiveValue; } @Override public short toShort() throws TypeMismatchException { - return SpLib.convStringToShort(value); + return SpLib.convStringToShort(toString()); } @Override public int toInt() throws TypeMismatchException { - return SpLib.convStringToInt(value); + return SpLib.convStringToInt(toString()); } @Override public long toLong() throws TypeMismatchException { - return SpLib.convStringToBigint(value); + return SpLib.convStringToBigint(toString()); } @Override public float toFloat() throws TypeMismatchException { - return SpLib.convStringToFloat(value); + return SpLib.convStringToFloat(toString()); } @Override public double toDouble() throws TypeMismatchException { - return SpLib.convStringToDouble(value); + return SpLib.convStringToDouble(toString()); } @Override public Byte toByteObject() throws TypeMismatchException { - return SpLib.convStringToByte(value); + return SpLib.convStringToByte(toString()); } @Override public Short toShortObject() throws TypeMismatchException { - return SpLib.convStringToShort(value); + return SpLib.convStringToShort(toString()); } @Override public Integer toIntegerObject() throws TypeMismatchException { - return SpLib.convStringToInt(value); + return SpLib.convStringToInt(toString()); } @Override public Long toLongObject() throws TypeMismatchException { - return SpLib.convStringToBigint(value); + return SpLib.convStringToBigint(toString()); } @Override public Float toFloatObject() throws TypeMismatchException { - return SpLib.convStringToFloat(value); + return SpLib.convStringToFloat(toString()); } @Override public Double toDoubleObject() throws TypeMismatchException { - return SpLib.convStringToDouble(value); + return SpLib.convStringToDouble(toString()); } @Override public Date toDate() throws TypeMismatchException { - return SpLib.convStringToDate(value); + return SpLib.convStringToDate(toString()); } @Override public Time toTime() throws TypeMismatchException { - return SpLib.convStringToTime(value); + return SpLib.convStringToTime(toString()); } @Override public Timestamp toTimestamp() throws TypeMismatchException { - return SpLib.convStringToTimestamp(value); + return SpLib.convStringToTimestamp(toString()); } @Override public Timestamp toDatetime() throws TypeMismatchException { - return SpLib.convStringToDatetime(value); + return SpLib.convStringToDatetime(toString()); } @Override public BigDecimal toBigDecimal() throws TypeMismatchException { - return SpLib.convStringToNumeric(value); + return SpLib.convStringToNumeric(toString()); } @Override public Object toObject() throws TypeMismatchException { - return value; + return toString(); } @Override public String toString() { - return value; + if (resolved == null) { + try { + resolved = new String(primitiveValue, SysParam.getCodesetString(this.codeset)); + } catch (UnsupportedEncodingException e) { + // just return null + Server.log(e); + } + } + return (String) resolved; } } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/TimeValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/TimeValue.java index ac741401336..74df731983d 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/TimeValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/TimeValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.sql.Time; @@ -51,20 +52,12 @@ public TimeValue(int hour, int min, int sec) { cal.set(Calendar.MILLISECOND, 0); this.time = new Time(cal.getTimeInMillis()); - } - - public TimeValue(int hour, int min, int sec, int mode, int dbType) { - super(mode); - Calendar cal = Calendar.getInstance(); - cal.set(0, 0, 0, hour, min, sec); - cal.set(Calendar.MILLISECOND, 0); - - this.time = new Time(cal.getTimeInMillis()); - this.dbType = dbType; + this.dbType = DBType.DB_TIME; } public TimeValue(Time time) { this.time = time; + this.dbType = DBType.DB_TIME; assert time.getTime() % 1000L == 0; } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/TimestampValue.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/TimestampValue.java index 9757907df43..25e20d899c7 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/TimestampValue.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/TimestampValue.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.plcsql.predefined.sp.SpLib; import java.sql.Date; @@ -54,33 +55,19 @@ public TimestampValue(int year, int mon, int day, int hour, int min, int sec) cal.set(Calendar.MILLISECOND, 0); this.timestamp = new Timestamp(cal.getTimeInMillis()); + this.dbType = DBType.DB_TIMESTAMP; if (SpLib.checkTimestamp(timestamp) == null) { throw new TypeMismatchException("invalid Timestamp " + timestamp); } } - public TimestampValue( - int year, int mon, int day, int hour, int min, int sec, int mode, int dbType) - throws TypeMismatchException { - super(mode); - Calendar cal = Calendar.getInstance(); - cal.clear(); - cal.set(year, mon, day, hour, min, sec); - cal.set(Calendar.MILLISECOND, 0); - - this.timestamp = new Timestamp(cal.getTimeInMillis()); - if (SpLib.checkTimestamp(timestamp) == null) { - throw new TypeMismatchException("invalid Timestamp " + timestamp); - } - this.dbType = dbType; - } - public TimestampValue(Timestamp timestamp) throws TypeMismatchException { if (timestamp != null && (timestamp.getTime() % 1000L != 0L || SpLib.checkTimestamp(timestamp) == null)) { throw new TypeMismatchException("invalid Timestamp " + timestamp); } this.timestamp = timestamp; + this.dbType = DBType.DB_TIMESTAMP; } @Override diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/Value.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/Value.java index 543f230e076..438ccbeb2cb 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/Value.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/Value.java @@ -31,6 +31,7 @@ package com.cubrid.jsp.value; +import com.cubrid.jsp.Server; import com.cubrid.jsp.exception.TypeMismatchException; import com.cubrid.jsp.impl.SUConnection; import cubrid.sql.CUBRIDOID; @@ -48,13 +49,11 @@ public abstract class Value { protected int mode; protected Object resolved; protected int dbType; + protected int codeset; public Value() { this.mode = IN; - } - - public Value(int mode) { - this.mode = mode; + this.codeset = Server.getConfig().getServerCodesetId(); } public void setMode(int mode) { @@ -329,6 +328,10 @@ public void setDbType(int type) { dbType = type; } + public int getCodeSet() { + return codeset; + } + // ----------------------------------------------------- private String getCastErrMsg(String targetType) { diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ValueUtilities.java b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ValueUtilities.java index dae02f629e3..e390816ffc9 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ValueUtilities.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/jsp/value/ValueUtilities.java @@ -32,7 +32,11 @@ package com.cubrid.jsp.value; import com.cubrid.jsp.data.DBType; +import com.cubrid.jsp.exception.ExecuteException; import com.cubrid.jsp.exception.TypeMismatchException; +import cubrid.sql.CUBRIDOID; +import java.math.BigDecimal; +import java.sql.ResultSet; public class ValueUtilities { public static Object resolveValue(int dbType, Value value) throws TypeMismatchException { @@ -92,4 +96,61 @@ public static Object resolveValue(int dbType, Value value) throws TypeMismatchEx } return resolvedResult; } + + public static Value createValueFrom(Object o) throws TypeMismatchException, ExecuteException { + Value val = null; + + if (o == null) { + val = new NullValue(); + } else if (o instanceof Boolean) { + val = new BooleanValue(((Boolean) o).booleanValue()); + } else if (o instanceof Byte) { + val = new ByteValue(((Byte) o).byteValue()); + } else if (o instanceof Short) { + val = new ShortValue(((Short) o).shortValue()); + } else if (o instanceof Integer) { + val = new IntValue(((Integer) o).intValue()); + } else if (o instanceof Long) { + val = new LongValue(((Long) o).longValue()); + } else if (o instanceof Float) { + val = new FloatValue(((Float) o).floatValue()); + } else if (o instanceof Double) { + val = new DoubleValue(((Double) o).doubleValue()); + } else if (o instanceof BigDecimal) { + val = new NumericValue(((BigDecimal) o)); + } else if (o instanceof String) { + val = new StringValue((String) o); + } else if (o instanceof java.sql.Date) { + val = new DateValue((java.sql.Date) o); + } else if (o instanceof java.sql.Time) { + val = new TimeValue((java.sql.Time) o); + } else if (o instanceof java.sql.Timestamp) { + val = + new DatetimeValue( + (java.sql.Timestamp) + o); // DatetimeValue allows more values than TimestampValue + } else if (o instanceof CUBRIDOID) { + val = new OidValue((CUBRIDOID) o); + } else if (o instanceof ResultSet) { + val = new ResultSetValue((ResultSet) o); + } else if (o instanceof byte[]) { + val = new StringValue((byte[]) o); + } else if (o instanceof short[]) { + val = new SetValue((short[]) o); + } else if (o instanceof int[]) { + val = new SetValue((int[]) o); + } else if (o instanceof long[]) { + val = new SetValue((long[]) o); + } else if (o instanceof float[]) { + val = new SetValue((float[]) o); + } else if (o instanceof double[]) { + val = new SetValue((double[]) o); + } else if (o instanceof Object[]) { + val = new SetValue((Object[]) o); + } else { + throw new ExecuteException("Not supported data type: '" + o.getClass().getName() + "'"); + } + + return val; + } } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/Misc.java b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/Misc.java index 4666596881d..a8c5ced44f6 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/Misc.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/Misc.java @@ -38,6 +38,7 @@ import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; public class Misc { @@ -91,6 +92,17 @@ public static String detachPkgName(String routineName) { return idx >= 0 ? routineName.substring(idx + 1) : routineName; } + public static int[] getLineColumnOf(TerminalNode node) { + if (node == null) { + return UNKNOWN_LINE_COLUMN; + } + + Token start = node.getSymbol(); + assert start != null; + + return new int[] {start.getLine(), start.getCharPositionInLine() + 1}; + } + public static int[] getLineColumnOf(ParserRuleContext ctx) { if (ctx == null) { return UNKNOWN_LINE_COLUMN; diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/ParseTreeConverter.java b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/ParseTreeConverter.java index 46ed3aeb40c..4d51c5862a0 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/ParseTreeConverter.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/ParseTreeConverter.java @@ -36,13 +36,12 @@ import com.cubrid.jsp.data.ColumnInfo; import com.cubrid.jsp.data.DBType; import com.cubrid.jsp.value.DateTimeParser; +import com.cubrid.plcsql.compiler.antlrgen.PlcParser.Create_routineContext; import com.cubrid.plcsql.compiler.antlrgen.PlcParserBaseVisitor; import com.cubrid.plcsql.compiler.antlrgen.StaticSqlWithRecordsLexer; import com.cubrid.plcsql.compiler.antlrgen.StaticSqlWithRecordsParser; import com.cubrid.plcsql.compiler.ast.*; -import com.cubrid.plcsql.compiler.error.SemanticError; -import com.cubrid.plcsql.compiler.error.SyntaxError; -import com.cubrid.plcsql.compiler.error.UndeclaredId; +import com.cubrid.plcsql.compiler.error.*; import com.cubrid.plcsql.compiler.serverapi.*; import com.cubrid.plcsql.compiler.type.*; import java.math.BigDecimal; @@ -70,8 +69,10 @@ public class ParseTreeConverter extends PlcParserBaseVisitor { public final SymbolStack symbolStack = new SymbolStack(); - public ParseTreeConverter(InstanceStore iStore) { + public ParseTreeConverter(InstanceStore iStore, String spOwner, String spRevision) { this.iStore = iStore; + this.spOwner = Misc.getNormalizedText(spOwner); + this.spRevision = spRevision; } public void askServerSemanticQuestions() { @@ -231,10 +232,9 @@ public AstNode visitSql_script(Sql_scriptContext ctx) { @Override public Unit visitCreate_routine(Create_routineContext ctx) { - previsitRoutine_definition(ctx.routine_definition(), null); DeclRoutine decl = visitRoutine_definition(ctx.routine_definition()); - return new Unit(ctx, autonomousTransaction, connectionRequired, imports, decl); + return new Unit(ctx, autonomousTransaction, connectionRequired, decl, spRevision); } @Override @@ -244,7 +244,7 @@ public NodeList visitParameter_list(Parameter_listContext ctx) { return EMPTY_PARAMS; } - boolean ofTopLevel = symbolStack.getCurrentScope().level == 2; + boolean ofTopLevel = symbolStack.getCurrentScope().level == (SymbolStack.LEVEL_MAIN + 1); NodeList ret = new NodeList<>(); if (ofTopLevel) { for (ParameterContext pc : ctx.parameter()) { @@ -947,9 +947,31 @@ public Expr visitRecord_field(Record_fieldContext ctx) { @Override public Expr visitFunction_call(Function_callContext ctx) { - String name = Misc.getNormalizedText(ctx.function_name()); + String name = Misc.getNormalizedText(ctx.func_call_name().name); NodeList args = visitFunction_argument(ctx.function_argument()); + if (ctx.func_call_name().owner != null) { + // This has an owner name + + String owner = Misc.getNormalizedText(ctx.func_call_name().owner); + if (owner.equals(spOwner) && name.equals(spName) && isSpFunc) { + + // OK: recursive call of the stored function being defined + // Note that owner name is unused afterwards. + } else { + + // This has an owner name and the target function is not the SP being defined + // Take this as a global function call. + connectionRequired = true; + + String uniqName = owner + '.' + name; + ExprGlobalFuncCall ret = new ExprGlobalFuncCall(ctx, uniqName, args); + semanticQuestions.put(ret, new ServerAPI.FunctionSignature(uniqName)); + + return ret; // done + } + } + DeclFunc decl = symbolStack.getDeclFunc(name); if (decl == null) { @@ -1247,17 +1269,17 @@ public AstNode visitCursor_definition(Cursor_definitionContext ctx) { @Override public DeclRoutine visitRoutine_definition(Routine_definitionContext ctx) { - if (ctx.LANGUAGE() != null && symbolStack.getCurrentScope().level > 1) { + if (ctx.LANGUAGE() != null + && symbolStack.getCurrentScope().level > SymbolStack.LEVEL_MAIN) { int[] lineColumn = Misc.getLineColumnOf(ctx); throw new SyntaxError( lineColumn[0], lineColumn[1], "illegal keywords LANGUAGE PLCSQL for a local procedure/function"); } + String name = Misc.getNormalizedText(ctx.routine_uniq_name().name); - String name = Misc.getNormalizedText(ctx.identifier()); boolean isFunction = (ctx.PROCEDURE() == null); - symbolStack.pushSymbolTable( name, isFunction ? Misc.RoutineType.FUNC : Misc.RoutineType.PROC); @@ -1418,7 +1440,7 @@ public Expr visitIdentifier(IdentifierContext ctx) { if (idUsedInCurrentDeclPart != null) { idUsedInCurrentDeclPart.put( - name, new UseAndDeclLevel(ctx, symbolStack.LEVEL_PREDEFINED)); + name, new UseAndDeclLevel(ctx, SymbolStack.LEVEL_PREDEFINED)); } // this is possibly a global function call @@ -1489,6 +1511,32 @@ public Expr visitIdentifier(IdentifierContext ctx) { throw new RuntimeException("unreachable"); } + @Override + public Expr visitKeyword_builtin_func(Keyword_builtin_funcContext ctx) { + String name = Misc.getNormalizedText(ctx); + + Decl decl = symbolStack.getDeclForIdExpr(name); + assert decl != null; + Scope scope = symbolStack.getCurrentScope(); + if (idUsedInCurrentDeclPart != null && decl.scope.level < scope.level) { + idUsedInCurrentDeclPart.put(name, new UseAndDeclLevel(ctx, decl.scope.level)); + } + + if (decl instanceof DeclId) { + return new ExprId(ctx, name, scope, (DeclId) decl); + } else if (decl instanceof DeclFunc) { + if (decl.scope().level == SymbolStack.LEVEL_PREDEFINED) { + connectionRequired = true; + return new ExprBuiltinFuncCall(ctx, name, EMPTY_ARGS); + } else { + return new ExprLocalFuncCall(ctx, name, EMPTY_ARGS, scope, (DeclFunc) decl); + } + } + + assert false : "unreachable"; + throw new RuntimeException("unreachable"); + } + @Override public Stmt visitContinue_statement(Continue_statementContext ctx) { @@ -2107,16 +2155,41 @@ public StmtRollback visitRollback_statement(Rollback_statementContext ctx) { @Override public AstNode visitProcedure_call(Procedure_callContext ctx) { - String name = Misc.getNormalizedText(ctx.routine_name()); - if (ctx.DBMS_OUTPUT() != null && dbmsOutputProc.contains(name)) { + String name = Misc.getNormalizedText(ctx.proc_call_name().name); + NodeList args = visitFunction_argument(ctx.function_argument()); + + if (ctx.proc_call_name().owner != null) { + // This has an owner name + + String owner = Misc.getNormalizedText(ctx.proc_call_name().owner); + if (owner.equals(spOwner) + && ctx.proc_call_name().DBMS_OUTPUT() == null + && name.equals(spName) + && !isSpFunc) { + + // OK: recursive call of the stored procedure being defined + // Note that owner name is unused afterwards. + } else { + + // This has an owner name and the target procedure is not the SP being defined + // Take this as a global procedure call. + connectionRequired = true; + + String uniqName = owner + '.' + name; + StmtGlobalProcCall ret = new StmtGlobalProcCall(ctx, uniqName, args); + semanticQuestions.put(ret, new ServerAPI.ProcedureSignature(uniqName)); + + return ret; // done + } + } + + if (ctx.proc_call_name().DBMS_OUTPUT() != null && dbmsOutputProc.contains(name)) { // DBMS_OUTPUT is not an actual package but just a syntactic "ornament" to ease // migration from Oracle. // NOTE: users cannot define a procedure of this name because of '$' name = "DBMS_OUTPUT$" + name; } - NodeList args = visitFunction_argument(ctx.function_argument()); - DeclProc decl = symbolStack.getDeclProc(name); if (decl == null) { @@ -2361,7 +2434,11 @@ private static class UseAndDeclLevel { private final LinkedHashMap semanticQuestions = new LinkedHashMap<>(); - private final Set imports = new TreeSet<>(); + private final String spOwner; + private final String spRevision; + + private String spName; + private boolean isSpFunc; private int exHandlerDepth; @@ -2457,7 +2534,40 @@ private void previsitCursor_definition(Cursor_definitionContext ctx) { private void previsitRoutine_definition( Routine_definitionContext ctx, Map store) { - String name = Misc.getNormalizedText(ctx.identifier()); + String name = Misc.getNormalizedText(ctx.routine_uniq_name().name); + + if (symbolStack.getCurrentScope().level > SymbolStack.LEVEL_MAIN) { + + // local procedure/function + + if (ctx.LANGUAGE() != null) { + throw new SemanticError( + Misc.getLineColumnOf(ctx.LANGUAGE()), // s083 + "illegal keywords LANGUAGE PLCSQL for a local procedure/function"); + } + if (ctx.authid_spec() != null) { + throw new SemanticError( + Misc.getLineColumnOf(ctx.LANGUAGE()), // s084 + "illegal keyword AUTHID for a local procedure/function"); + } + if (ctx.routine_uniq_name().owner != null) { + throw new SemanticError( + Misc.getLineColumnOf(ctx.routine_uniq_name().owner), // s085 + "owner specification is not allowed for local procedures/functions"); + } + } else { + + // SP being defined + + assert symbolStack.getCurrentScope().level == SymbolStack.LEVEL_MAIN; + spName = name; + isSpFunc = (ctx.PROCEDURE() == null); + } + + if (ctx.routine_uniq_name().owner != null) { + String owner = Misc.getNormalizedText(ctx.routine_uniq_name().owner); + assert owner.equals(spOwner); + } // push a temporary symbol table, in order not to corrupt the current symbol table with the // parameters diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/PlcsqlCompilerMain.java b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/PlcsqlCompilerMain.java index b986c75b600..345847de868 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/PlcsqlCompilerMain.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/PlcsqlCompilerMain.java @@ -46,7 +46,16 @@ public class PlcsqlCompilerMain { - public static CompileInfo compilePLCSQL(String in, boolean verbose) { + // temporary code - the owner and revision strings will come from the server + private static int revision = 1; + + public static CompileInfo compilePLCSQL(String in, String owner, boolean verbose) { + return compilePLCSQL(in, verbose, owner, Integer.toString(revision++)); + } + // end of temporary code + + public static CompileInfo compilePLCSQL( + String in, boolean verbose, String owner, String revision) { // System.out.println("[TEMP] text to the compiler"); // System.out.println(in); @@ -54,7 +63,7 @@ public static CompileInfo compilePLCSQL(String in, boolean verbose) { int optionFlags = verbose ? OPT_VERBOSE : 0; CharStream input = CharStreams.fromString(in); try { - return compileInner(new InstanceStore(), input, optionFlags); + return compileInner(new InstanceStore(), input, optionFlags, owner, revision); } catch (SyntaxError e) { CompileInfo err = new CompileInfo(-1, e.line, e.column, e.getMessage()); return err; @@ -84,6 +93,15 @@ private static ParseTree parse( } PlcLexerEx lexer = new PlcLexerEx(input); + + LexerErrorIndicator lei = new LexerErrorIndicator(); + lexer.removeErrorListeners(); + lexer.addErrorListener(lei); + + if (lei.hasError) { + throw new SyntaxError(lei.line, lei.column, lei.msg); + } + CommonTokenStream tokens = new CommonTokenStream(lexer); PlcParser parser = new PlcParser(tokens); @@ -133,7 +151,11 @@ private static long logElapsedTime(StringBuilder logStore, String msg, long t0) } private static CompileInfo compileInner( - InstanceStore iStore, CharStream input, int optionFlags) { + InstanceStore iStore, + CharStream input, + int optionFlags, + String owner, + String revision) { boolean verbose = (optionFlags & OPT_VERBOSE) > 0; @@ -175,7 +197,7 @@ private static CompileInfo compileInner( // ------------------------------------------ // converting parse tree to AST - ParseTreeConverter converter = new ParseTreeConverter(iStore); + ParseTreeConverter converter = new ParseTreeConverter(iStore, owner, revision); Unit unit = (Unit) converter.visit(tree); if (verbose) { @@ -228,6 +250,31 @@ private static CompileInfo compileInner( return info; } + private static class LexerErrorIndicator extends BaseErrorListener { + + boolean hasError; + int line; + int column; + String msg; + + @Override + public void syntaxError( + Recognizer recognizer, + Object offendingSymbol, + int line, + int charPositionInLine, + String msg, + RecognitionException e) { + + if (msg.startsWith("token recognition error")) { + this.hasError = true; + this.line = line; + this.column = charPositionInLine + 1; // charPositionInLine starts from 0 + this.msg = msg; + } + } + } + private static class SyntaxErrorIndicator extends BaseErrorListener { boolean hasError; diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/ast/Unit.java b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/ast/Unit.java index 101adc30a69..5f3c07a2d4c 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/ast/Unit.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/ast/Unit.java @@ -32,7 +32,6 @@ import com.cubrid.plcsql.compiler.visitor.AstVisitor; import java.sql.*; -import java.util.Set; import org.antlr.v4.runtime.ParserRuleContext; public class Unit extends AstNode { @@ -44,23 +43,23 @@ public R accept(AstVisitor visitor) { public final boolean autonomousTransaction; public final boolean connectionRequired; - public final Set imports; public final DeclRoutine routine; + public final String revision; public Unit( ParserRuleContext ctx, boolean autonomousTransaction, boolean connectionRequired, - Set imports, - DeclRoutine routine) { + DeclRoutine routine, + String revision) { super(ctx); assert routine.scope.level == 1; this.autonomousTransaction = autonomousTransaction; this.connectionRequired = connectionRequired; - this.imports = imports; this.routine = routine; + this.revision = revision; } public String getJavaSignature() { @@ -95,25 +94,15 @@ public String getClassName() { if (className == null) { String kindStr = routine.isProcedure() ? "Proc" : "Func"; - className = String.format("%s_%s", kindStr, routine.name); + className = String.format("%s_%s_%s", kindStr, routine.name, revision); } return className; } - public String[] getImportsArray() { - if (imports.size() == 0) { - return new String[] {"// no imports"}; - } else { - return imports.toArray(dummyStrArr); - } - } - // ------------------------------------------ // Private // ------------------------------------------ - private static final String[] dummyStrArr = new String[0]; - private String className; } diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/type/TypeChar.java b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/type/TypeChar.java index fb5ca0c0f08..e5101817ef3 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/type/TypeChar.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/compiler/type/TypeChar.java @@ -34,7 +34,7 @@ public class TypeChar extends Type { - public static final int MAX_LEN = 2048; + public static final int MAX_LEN = 268435455; public final int length; diff --git a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/predefined/sp/SpLib.java b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/predefined/sp/SpLib.java index 2b1963d8bf1..c33ea2ecb22 100644 --- a/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/predefined/sp/SpLib.java +++ b/pl_engine/pl_server/src/main/java/com/cubrid/plcsql/predefined/sp/SpLib.java @@ -31,6 +31,7 @@ package com.cubrid.plcsql.predefined.sp; import com.cubrid.jsp.Server; +import com.cubrid.jsp.SysParam; import com.cubrid.jsp.value.DateTimeParser; import com.cubrid.plcsql.builtin.DBMS_OUTPUT; import com.cubrid.plcsql.compiler.CoercionScheme; @@ -48,7 +49,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.ZoneOffset; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; @@ -701,7 +702,7 @@ public static Boolean opNot(Boolean l) { // is null @Operator(coercionScheme = CoercionScheme.ObjectOp) public static Boolean opIsNull(Object l) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -778,7 +779,7 @@ public static Double opNeg(Double l) { @Operator(coercionScheme = CoercionScheme.ArithOp) public static Object opNeg(Object l) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -853,7 +854,7 @@ public static Long opBitCompli(Long l) { @Operator(coercionScheme = CoercionScheme.IntArithOp) public static Object opBitCompli(Object l) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -940,7 +941,7 @@ public static Boolean opEq(Boolean l, Boolean r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opEq(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -953,7 +954,7 @@ public static Boolean opEq(String l, String r) { } public static Boolean opEqChar(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1036,7 +1037,7 @@ public static Boolean opEqTimestamp(Timestamp l, Timestamp r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opEq(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1061,7 +1062,7 @@ public static Boolean opNullSafeEq(Boolean l, Boolean r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opNullSafeEq(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1074,7 +1075,7 @@ public static Boolean opNullSafeEq(String l, String r) { } public static Boolean opNullSafeEqChar(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1169,7 +1170,7 @@ public static Boolean opNullSafeEqTimestamp(Timestamp l, Timestamp r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opNullSafeEq(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1197,7 +1198,7 @@ public static Boolean opNeq(Boolean l, Boolean r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opNeq(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1284,7 +1285,7 @@ public static Boolean opNeqTimestamp(Timestamp l, Timestamp r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opNeq(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1310,7 +1311,7 @@ public static Boolean opLe(Boolean l, Boolean r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opLe(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1323,7 +1324,7 @@ public static Boolean opLe(String l, String r) { } public static Boolean opLeChar(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1406,7 +1407,7 @@ public static Boolean opLeTimestamp(Timestamp l, Timestamp r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opLe(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1430,7 +1431,7 @@ public static Boolean opGe(Boolean l, Boolean r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opGe(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1443,7 +1444,7 @@ public static Boolean opGe(String l, String r) { } public static Boolean opGeChar(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1526,7 +1527,7 @@ public static Boolean opGeTimestamp(Timestamp l, Timestamp r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opGe(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1550,7 +1551,7 @@ public static Boolean opLt(Boolean l, Boolean r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opLt(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1563,7 +1564,7 @@ public static Boolean opLt(String l, String r) { } public static Boolean opLtChar(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1646,7 +1647,7 @@ public static Boolean opLtTimestamp(Timestamp l, Timestamp r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opLt(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1671,7 +1672,7 @@ public static Boolean opGt(Boolean l, Boolean r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opGt(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1684,7 +1685,7 @@ public static Boolean opGt(String l, String r) { } public static Boolean opGtChar(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1767,7 +1768,7 @@ public static Boolean opGtTimestamp(Timestamp l, Timestamp r) { @Operator(coercionScheme = CoercionScheme.CompOp) public static Boolean opGt(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -1795,7 +1796,7 @@ public static Boolean opBetween(Boolean o, Boolean lower, Boolean upper) { @Operator(coercionScheme = CoercionScheme.NAryCompOp) public static Boolean opBetween(String o, String lower, String upper) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(o)) { o = null; } @@ -1814,7 +1815,7 @@ public static Boolean opBetween(String o, String lower, String upper) { } public static Boolean opBetweenChar(String o, String lower, String upper) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(o)) { o = null; } @@ -1929,7 +1930,7 @@ public static Boolean opBetweenTimestamp(Timestamp o, Timestamp lower, Timestamp @Operator(coercionScheme = CoercionScheme.NAryCompOp) public static Boolean opBetween(Object o, Object lower, Object upper) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(o)) { o = null; } @@ -1967,7 +1968,7 @@ public static Boolean opIn(String o, String... arr) { public static Boolean opInChar(String o, String... arr) { assert arr != null; - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(o)) { o = null; } @@ -1980,7 +1981,7 @@ public static Boolean opInChar(String o, String... arr) { boolean nullFound = false; for (String p : arr) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(p)) { p = null; } @@ -2085,7 +2086,7 @@ public static Boolean opInTimestamp(Timestamp o, Timestamp... arr) { public static Boolean opIn(Object o, Object... arr) { assert arr != null; - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(o)) { o = null; } @@ -2096,7 +2097,7 @@ public static Boolean opIn(Object o, Object... arr) { } boolean nullFound = false; for (Object p : arr) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(p)) { p = null; } @@ -2196,7 +2197,7 @@ public static Double opMult(Double l, Double r) { @Operator(coercionScheme = CoercionScheme.ArithOp) public static Object opMult(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -2222,7 +2223,7 @@ public static Object opDiv(Short l, Short r) { if (r.equals((short) 0)) { throw new ZERO_DIVIDE(); } - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_COMPAT_NUMBER_BEHAVIOR)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_COMPAT_NUMBER_BEHAVIOR)) { return opDiv(BigDecimal.valueOf(l.longValue()), BigDecimal.valueOf(r.longValue())); } else { return (short) (l / r); @@ -2237,7 +2238,7 @@ public static Object opDiv(Integer l, Integer r) { if (r.equals(0)) { throw new ZERO_DIVIDE(); } - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_COMPAT_NUMBER_BEHAVIOR)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_COMPAT_NUMBER_BEHAVIOR)) { return opDiv(BigDecimal.valueOf(l.longValue()), BigDecimal.valueOf(r.longValue())); } else { return l / r; @@ -2253,7 +2254,7 @@ public static Object opDiv(Long l, Long r) { throw new ZERO_DIVIDE(); } - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_COMPAT_NUMBER_BEHAVIOR)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_COMPAT_NUMBER_BEHAVIOR)) { return opDiv(BigDecimal.valueOf(l), BigDecimal.valueOf(r)); } else { return l / r; @@ -2275,7 +2276,7 @@ public static BigDecimal opDiv(BigDecimal l, BigDecimal r) { int s2 = r.scale(); int scale; - if (Server.getSystemParameterBool(Server.SYS_PARAM_COMPAT_NUMERIC_DIVISION_SCALE)) { + if (Server.getSystemParameterBool(SysParam.COMPAT_NUMERIC_DIVISION_SCALE)) { scale = Math.max(s1, s2); } else { scale = Math.max(9, Math.max(s1, s2)); @@ -2324,7 +2325,7 @@ public static Double opDiv(Double l, Double r) { @Operator(coercionScheme = CoercionScheme.ArithOp) public static Object opDiv(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -2377,7 +2378,7 @@ public static Long opDivInt(Long l, Long r) { @Operator(coercionScheme = CoercionScheme.IntArithOp) public static Object opDivInt(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -2430,7 +2431,7 @@ public static Long opMod(Long l, Long r) { @Operator(coercionScheme = CoercionScheme.IntArithOp) public static Object opMod(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -2450,7 +2451,7 @@ public static Object opMod(Object l, Object r) { // + @Operator(coercionScheme = CoercionScheme.ArithOp) public static String opAdd(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (l == null) { l = EMPTY_STRING; } @@ -2644,7 +2645,7 @@ public static Timestamp opAddTimestamp(Long l, Timestamp r) { @Operator(coercionScheme = CoercionScheme.ArithOp) public static Object opAdd(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -2878,7 +2879,7 @@ public static Timestamp opSubtractTimestamp(Timestamp l, Long r) { @Operator(coercionScheme = CoercionScheme.ArithOp) public static Object opSubtract(Object l, Object r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(l)) { l = null; } @@ -2898,7 +2899,7 @@ public static Object opSubtract(Object l, Object r) { // || @Operator(coercionScheme = CoercionScheme.StringOp) public static String opConcat(String l, String r) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (l == null) { l = EMPTY_STRING; } @@ -3149,7 +3150,7 @@ public static String convTimestampToString(Timestamp e) { } Instant instant = Instant.ofEpochMilli(e.getTime()); - ZoneOffset timezone = Server.getSystemParameterTimezone(Server.SYS_PARAM_TIMEZONE); + ZoneId timezone = Server.getConfig().getTimeZone(); ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, timezone); return zdt.format(TIMESTAMP_FORMAT); } @@ -3202,7 +3203,7 @@ public static String convDoubleToString(Double e) { return null; } - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_COMPAT_NUMBER_BEHAVIOR)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_COMPAT_NUMBER_BEHAVIOR)) { BigDecimal bd = new BigDecimal(e.doubleValue(), doubleToStringContext); return detachTrailingZeros(bd.toPlainString()); } else { @@ -3286,7 +3287,7 @@ public static String convFloatToString(Float e) { return null; } - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_COMPAT_NUMBER_BEHAVIOR)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_COMPAT_NUMBER_BEHAVIOR)) { BigDecimal bd = new BigDecimal(e.doubleValue(), floatToStringContext); return detachTrailingZeros(bd.toPlainString()); } else { @@ -3361,7 +3362,7 @@ public static String convNumericToString(BigDecimal e) { return null; } - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_COMPAT_NUMBER_BEHAVIOR)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_COMPAT_NUMBER_BEHAVIOR)) { return detachTrailingZeros(e.toPlainString()); } else { return e.toString(); @@ -4275,7 +4276,7 @@ private static Boolean commonOpGt(Comparable l, Comparable r) { private static Boolean commonOpIn(Object o, Object... arr) { assert arr != null; - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(o)) { o = null; } @@ -4286,7 +4287,7 @@ private static Boolean commonOpIn(Object o, Object... arr) { } boolean nullFound = false; for (Object p : arr) { - if (Server.getSystemParameterBool(Server.SYS_PARAM_ORACLE_STYLE_EMPTY_STRING)) { + if (Server.getSystemParameterBool(SysParam.ORACLE_STYLE_EMPTY_STRING)) { if (EMPTY_STRING.equals(p)) { p = null; } diff --git a/sa/CMakeLists.txt b/sa/CMakeLists.txt index bd781365546..130822f842b 100644 --- a/sa/CMakeLists.txt +++ b/sa/CMakeLists.txt @@ -98,6 +98,7 @@ set(BASE_SOURCES ${BASE_DIR}/pinnable_buffer.cpp ${BASE_DIR}/pinning.cpp ${BASE_DIR}/printer.cpp + ${BASE_DIR}/process_util.c ${BASE_DIR}/ini_parser.c ${BASE_DIR}/system_parameter.c ${BASE_DIR}/fault_injection.c @@ -184,6 +185,8 @@ set(CONNECTION_SOURCES ) set(COMMUNICATION_SOURCES + ${COMMUNICATION_DIR}/network_callback_cl.cpp + ${COMMUNICATION_DIR}/network_callback_sr.cpp ${COMMUNICATION_DIR}/network_interface_cl.c ${COMMUNICATION_DIR}/network_histogram.cpp ) @@ -343,35 +346,41 @@ set(OBJECT_HEADERS ) set(SP_SOURCES - ${SP_DIR}/jsp_cl.c - ${SP_DIR}/jsp_comm.c - ${SP_DIR}/jsp_file.c - ${SP_DIR}/jsp_sr.c - ) + ${SP_DIR}/jsp_cl.cpp + ${SP_DIR}/method_invoke_group.cpp + ${SP_DIR}/pl_connection.cpp + ${SP_DIR}/pl_compile_handler.cpp + ${SP_DIR}/pl_execution_stack_context.cpp + ${SP_DIR}/pl_executor.cpp + ${SP_DIR}/pl_query_cursor.cpp + ${SP_DIR}/pl_session.cpp + ${SP_DIR}/pl_signature.cpp + ${SP_DIR}/pl_comm.c + ${SP_DIR}/pl_file.c + ${SP_DIR}/pl_sr.cpp + ${SP_DIR}/pl_sr_jvm.cpp + ${SP_DIR}/sp_catalog.cpp + ${SP_DIR}/sp_code.cpp + ) + +set(SP_HEADERS + ${SP_DIR}/pl_connection.hpp + ${SP_DIR}/pl_execution_stack_context.hpp + ${SP_DIR}/pl_signature.hpp + ${SP_DIR}/pl_struct_compile.cpp +) set(METHOD_SOURCES ${METHOD_DIR}/method_callback.cpp - ${METHOD_DIR}/method_connection_cl.cpp - ${METHOD_DIR}/method_connection_sr.cpp - ${METHOD_DIR}/method_connection_java.cpp - ${METHOD_DIR}/method_connection_pool.cpp - ${METHOD_DIR}/method_compile_def.cpp - ${METHOD_DIR}/method_compile.cpp - ${METHOD_DIR}/method_def.cpp ${METHOD_DIR}/method_error.cpp ${METHOD_DIR}/method_scan.cpp - ${METHOD_DIR}/method_invoke_builtin.cpp - ${METHOD_DIR}/method_invoke_java.cpp ${METHOD_DIR}/method_struct_parameter_info.cpp ${METHOD_DIR}/method_struct_invoke.cpp ${METHOD_DIR}/method_struct_value.cpp ${METHOD_DIR}/method_struct_query.cpp ${METHOD_DIR}/method_struct_oid_info.cpp - ${METHOD_DIR}/method_invoke_group.cpp - ${METHOD_DIR}/method_runtime_context.cpp ${METHOD_DIR}/method_query_util.cpp ${METHOD_DIR}/method_query_handler.cpp - ${METHOD_DIR}/method_query_cursor.cpp ${METHOD_DIR}/method_oid_handler.cpp ${METHOD_DIR}/query_method.cpp ) @@ -634,6 +643,7 @@ add_library(cubridsa SHARED ${EXECUTABLE_SOURCES} ${HEAPLAYER_SOURCES} ${SP_SOURCES} + ${SP_HEADERS} ${METHOD_SOURCES} ${MONITOR_HEADERS} ${MONITOR_SOURCES} diff --git a/src/api/db_stub.c b/src/api/db_stub.c index 7fee17a7e25..7331dd7368c 100644 --- a/src/api/db_stub.c +++ b/src/api/db_stub.c @@ -36,7 +36,7 @@ #include "system_parameter.h" #include "authenticate.h" #include "object_accessor.h" -#include "jsp_sr.h" +#include "pl_sr.h" #define API_PROGRAM_NAME "CUBRID C API" @@ -2708,7 +2708,7 @@ conn_restart_client (CI_CONN_STRUCTURE * pconn, const char *program, int print_v #if !defined(WINDOWS) #if defined(SA_MODE) && defined(LINUX) - if (!jsp_jvm_is_loaded ()) + if (!pl_jvm_is_loaded ()) { prev_sigfpe_handler = os_set_signal_handler (SIGFPE, sigfpe_handler); } diff --git a/src/base/error_code.h b/src/base/error_code.h index 114e687e1a4..8edfe4e24a9 100644 --- a/src/base/error_code.h +++ b/src/base/error_code.h @@ -1132,7 +1132,7 @@ #define ER_SP_INVALID_NAME -904 #define ER_SP_NETWORK_ERROR -905 #define ER_SP_INVAILD_JAVA_METHOD -906 -#define ER_SP_DROP_NOT_ALLOWED -907 +#define ER_SP_DROP_NOT_ALLOWED_PRIVILEGES -907 #define ER_SP_TOO_MANY_ARG_COUNT -908 #define ER_BO_MISSING_OR_INVALID_CATALOG -909 @@ -1738,12 +1738,19 @@ #define ER_SP_SERVER_CRASHED -1359 #define ER_SP_COMPILE_ERROR -1360 +#define ER_QPROC_RESULT_CACHE_INVALID -1361 + +#define ER_LOCALE_LANG_NOT_AVAILABLE -1362 +#define ER_SP_DROP_NOT_ALLOWED_SYSTEM_GENERATED -1363 +#define ER_SP_INVOKERS_RIGHTS_NOT_SUPPORTED -1364 + + +#define ER_AU_OWNER_ONLY_GRANT_PRIVILEGE -1365 + +#define ER_LAST_ERROR -1366 -#define ER_QPROC_RESULT_CACHE_INVALID -1361 -#define ER_LOCALE_LANG_NOT_AVAILABLE -1362 -#define ER_LAST_ERROR -1363 /* * CAUTION! diff --git a/src/base/memory_alloc.c b/src/base/memory_alloc.c index ce814b47c03..f9ab4fe0a58 100644 --- a/src/base/memory_alloc.c +++ b/src/base/memory_alloc.c @@ -718,6 +718,37 @@ db_private_strdup (THREAD_ENTRY * thrd, const char *s) return cp; } + +/* + * db_private_strndup () - duplicate string with size. memory for the duplicated + * string is obtanined by db_private_alloc + * return: pointer to duplicated str + * thrd(in): thread conext if it is server, otherwise NULL + * s(in): source string + * size(in): source string size + */ +char * +db_private_strndup (THREAD_ENTRY * thrd, const char *s, size_t size) +{ + char *cp; + + /* fast return */ + if (s == NULL) + { + return NULL; + } + + cp = (char *) db_private_alloc (thrd, size + 1); + + if (cp != NULL) + { + memcpy (cp, s, size); + cp[size] = '\0'; + } + + return cp; +} + /* * db_private_free () - call free function for current private heap * return: diff --git a/src/base/memory_alloc.h b/src/base/memory_alloc.h index 75ee1d0ad15..e5386bd1097 100644 --- a/src/base/memory_alloc.h +++ b/src/base/memory_alloc.h @@ -278,6 +278,7 @@ extern "C" { #endif extern char *db_private_strdup (THREAD_ENTRY * thrd, const char *s); + extern char *db_private_strndup (THREAD_ENTRY * thrd, const char *s, size_t size); #ifdef __cplusplus } #endif diff --git a/src/base/message_catalog.h b/src/base/message_catalog.h index caf127b7bd8..5e85f57ccb7 100644 --- a/src/base/message_catalog.h +++ b/src/base/message_catalog.h @@ -52,6 +52,7 @@ #define MSGCAT_SET_LOCK 14 #define MSGCAT_SET_IO 15 #define MSGCAT_SET_LOG 16 +#define MSGCAT_SET_GLOSSARY 17 /* Message id in the set MSGCAT_SET_GENERAL */ #define MSGCAT_GENERAL_DATABASE_INIT 1 diff --git a/src/base/msgcat_glossary.hpp b/src/base/msgcat_glossary.hpp new file mode 100644 index 00000000000..a3b3561a543 --- /dev/null +++ b/src/base/msgcat_glossary.hpp @@ -0,0 +1,44 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// +// Message catalog set for glossary +// + +#ifndef _MSGCAT_SET_GLOSSARY_HPP_ +#define _MSGCAT_SET_GLOSSARY_HPP_ + +#include "message_catalog.h" + +/* + * Message id in the set MSGCAT_SET_GLOSSARY + * in the message catalog MSGCAT_CATALOG_CUBRID (file cubrid.msg). + */ + +#define MSGCAT_GLOSSARY_START 1 +#define MSGCAT_GLOSSARY_CLASS 1 +#define MSGCAT_GLOSSARY_TRIGGER 2 +#define MSGCAT_GLOSSARY_SERIAL 3 +#define MSGCAT_GLOSSARY_SERVER 4 +#define MSGCAT_GLOSSARY_SYNONYM 5 +#define MSGCAT_GLOSSARY_PROCEDURE 6 + +#define MSGCAT_GET_GLOSSARY_MSG(id) \ + msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_GLOSSARY, id) + +#endif // _MSGCAT_SET_GLOSSARY_HPP_ diff --git a/src/base/object_representation.h b/src/base/object_representation.h index c5b0fdb8fe2..102b6c62106 100644 --- a/src/base/object_representation.h +++ b/src/base/object_representation.h @@ -1111,7 +1111,6 @@ extern char *or_unpack_setref (char *ptr, DB_SET ** ref); extern char *or_pack_listid (char *ptr, void *listid); extern char *or_pack_lock (char *ptr, LOCK lock); extern char *or_pack_set_header (char *buf, DB_TYPE stype, DB_TYPE etype, int bound_bits, int size); -extern char *or_pack_method_sig_list (char *ptr, void *method_sig_list); extern char *or_pack_set_node (char *ptr, void *set_node); #if defined(ENABLE_UNUSED_FUNCTION) extern char *or_pack_elo (char *ptr, void *elo); @@ -1187,7 +1186,6 @@ extern int or_packed_varbit_length (int bitlen); * this file (it references DB_TYPE) */ extern int or_listid_length (void *listid); -extern int or_method_sig_list_length (void *method_sig_list_ptr); extern int or_set_node_length (void *set_node_ptr); #if defined(ENABLE_UNUSED_FUNCTION) extern int or_elo_length (void *elo_ptr); diff --git a/src/base/packer.cpp b/src/base/packer.cpp index cae2af6ce80..2eecf7dd2f9 100644 --- a/src/base/packer.cpp +++ b/src/base/packer.cpp @@ -720,7 +720,8 @@ namespace cubpacking if (len >= max_str_size) { - assert (false); + assert (max_str_size == 0); + align (INT_ALIGNMENT); return; } if (len > 0) diff --git a/src/base/porting.c b/src/base/porting.c index f8d7eda3127..f21b4cb93c7 100644 --- a/src/base/porting.c +++ b/src/base/porting.c @@ -2549,6 +2549,22 @@ strtof_win (const char *nptr, char **endptr) f_val = (float) d_val; return f_val; } + +char * +strndup_win (const char *src, size_t size) +{ + char *dest = (char *) malloc (size + 1); + if (dest == NULL) + { + return NULL; + } + + memcpy (dest, src, size); + dest[size] = '\0'; + + return dest; +} + #endif #ifndef HAVE_STRLCPY diff --git a/src/base/porting.h b/src/base/porting.h index 89e1bdba7f1..a4cabe3b478 100644 --- a/src/base/porting.h +++ b/src/base/porting.h @@ -155,6 +155,8 @@ extern char *realpath (const char *path, char *resolved_path); #define vfprintf _vfprintf_p #define vprintf _vprintf_p #define strtof strtof_win +#define strndup strndup_win + #if defined (_WIN32) #define mktime mktime_for_win32 #endif @@ -997,6 +999,7 @@ extern int str_to_float (float *ret_p, char **end_p, const char *str_p); #if defined (WINDOWS) extern float strtof_win (const char *nptr, char **endptr); +extern char *strndup_win (const char *src, size_t size); #endif #ifndef HAVE_STRLCPY diff --git a/src/base/process_util.c b/src/base/process_util.c index 2ffdb5d7e67..4885d01a10b 100644 --- a/src/base/process_util.c +++ b/src/base/process_util.c @@ -40,8 +40,8 @@ #include "memory_wrapper.hpp" int -create_child_process (const char *const argv[], int wait_flag, const char *stdin_file, char *stdout_file, - char *stderr_file, int *exit_status) +create_child_process (const char *path, const char *const argv[], int wait_flag, const char *stdin_file, + char *stdout_file, char *stderr_file, int *exit_status) { #if defined(WINDOWS) int new_pid; @@ -126,8 +126,7 @@ create_child_process (const char *const argv[], int wait_flag, const char *stdin } res = - CreateProcess (argv[0], cmd_arg_ptr, NULL, NULL, inherit_flag, CREATE_NO_WINDOW, NULL, NULL, &start_info, - &proc_info); + CreateProcess (path, cmd_arg_ptr, NULL, NULL, inherit_flag, CREATE_NO_WINDOW, NULL, NULL, &start_info, &proc_info); free (cmd_arg_ptr); if (res == FALSE) @@ -329,7 +328,7 @@ create_child_process (const char *const argv[], int wait_flag, const char *stdin } } - rc = execv ((const char *) argv[0], (char *const *) argv); + rc = execv (path, (char *const *) argv); assert (false); return rc; } @@ -363,3 +362,58 @@ create_child_process (const char *const argv[], int wait_flag, const char *stdin } } #endif + +/* + * is_terminated_process() - test if the process is terminated + * return: true if the process is terminated, otherwise false + * pid(in): process id + */ +bool +is_terminated_process (const int pid) +{ +#if defined(WINDOWS) + HANDLE h_process; + + h_process = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid); + if (h_process == NULL) + { + return true; + } + else + { + CloseHandle (h_process); + return false; + } +#else /* WINDOWS */ + if (kill (pid, 0) == -1) + { + return true; + } + else + { + return false; + } +#endif /* WINDOWS */ +} + +/* + * terminate_process() - terminate the process of given pid + * return: void + * pid(in): process id + */ +void +terminate_process (int pid) +{ +#if defined(WINDOWS) + HANDLE phandle; + + phandle = OpenProcess (PROCESS_TERMINATE, FALSE, pid); + if (phandle) + { + TerminateProcess (phandle, 0); + CloseHandle (phandle); + } +#else /* ! WINDOWS */ + kill (pid, SIGTERM); +#endif /* ! WINDOWS */ +} diff --git a/src/base/process_util.h b/src/base/process_util.h index 3f9618f33cd..ef6b42a6043 100644 --- a/src/base/process_util.h +++ b/src/base/process_util.h @@ -24,8 +24,11 @@ #ifndef _PROCESS_UTIL_H_ #define _PROCESS_UTIL_H_ -int -create_child_process (const char *const argv[], int wait_flag, const char *stdin_file, char *stdout_file, - char *stderr_file, int *exit_status); +#include "porting.h" +EXPORT_IMPORT int create_child_process (const char *path, const char *const argv[], int wait_flag, + const char *stdin_file, char *stdout_file, char *stderr_file, int *exit_status); + +EXPORT_IMPORT bool is_terminated_process (const int pid); +EXPORT_IMPORT void terminate_process (const int pid); #endif /* _PROCESS_UTIL_H_ */ diff --git a/src/base/system_parameter.c b/src/base/system_parameter.c index 0c9c4130599..76ffde8b29c 100644 --- a/src/base/system_parameter.c +++ b/src/base/system_parameter.c @@ -434,6 +434,16 @@ static const char sysprm_ha_conf_file_name[] = "cubrid_ha.conf"; #define PRM_NAME_JAVA_STORED_PROCEDURE_UDS "java_stored_procedure_uds" +#define PRM_NAME_STORED_PROCEDURE "stored_procedure" + +#define PRM_NAME_STORED_PROCEDURE_PORT "stored_procedure_port" + +#define PRM_NAME_STORED_PROCEDURE_JVM_OPTIONS "stored_procedure_vm_options" + +#define PRM_NAME_STORED_PROCEDURE_DEBUG "stored_procedure_debug" + +#define PRM_NAME_STORED_PROCEDURE_UDS "stored_procedure_uds" + #define PRM_NAME_ALLOW_TRUNCATED_STRING "allow_truncated_string" #define PRM_NAME_COMPAT_PRIMARY_KEY "compat_primary_key" @@ -2305,29 +2315,29 @@ int PRM_ER_LOG_TDE = false; static int prm_er_log_tde_default = false; static unsigned int prm_er_log_tde_flag = 0; -bool PRM_JAVA_STORED_PROCEDURE = true; -static bool prm_java_stored_procedure_default = true; -static unsigned int prm_java_stored_procedure_flag = 0; +bool PRM_STORED_PROCEDURE = true; +static bool prm_stored_procedure_default = true; +static unsigned int prm_stored_procedure_flag = 0; -int PRM_JAVA_STORED_PROCEDURE_PORT = 0; -static int prm_java_stored_procedure_port_default = 0; -static int prm_java_stored_procedure_port_upper = 65535; -static int prm_java_stored_procedure_port_lower = 0; -static unsigned int prm_java_stored_procedure_port_flag = 0; +int PRM_STORED_PROCEDURE_PORT = 0; +static int prm_stored_procedure_port_default = 0; +static int prm_stored_procedure_port_upper = 65535; +static int prm_stored_procedure_port_lower = 0; +static unsigned int prm_stored_procedure_port_flag = 0; -const char *PRM_JAVA_STORED_PROCEDURE_JVM_OPTIONS = ""; -static const char *prm_java_stored_procedure_jvm_options_default = ""; -static unsigned int prm_java_stored_procedure_jvm_options_flag = 0; +const char *PRM_STORED_PROCEDURE_JVM_OPTIONS = ""; +static const char *prm_stored_procedure_jvm_options_default = ""; +static unsigned int prm_stored_procedure_jvm_options_flag = 0; -int PRM_JAVA_STORED_PROCEDURE_DEBUG = -1; -static int prm_java_stored_procedure_debug_default = -1; -static int prm_java_stored_procedure_debug_upper = 65535; -static int prm_java_stored_procedure_debug_lower = -1; -static unsigned int prm_java_stored_procedure_debug_flag = 0; +int PRM_STORED_PROCEDURE_DEBUG = -1; +static int prm_stored_procedure_debug_default = -1; +static int prm_stored_procedure_debug_upper = 65535; +static int prm_stored_procedure_debug_lower = -1; +static unsigned int prm_stored_procedure_debug_flag = 0; -bool PRM_JAVA_STORED_PROCEDURE_UDS = true; -static bool prm_java_stored_procedure_uds_default = true; -static unsigned int prm_java_stored_procedure_uds_flag = 0; +bool PRM_STORED_PROCEDURE_UDS = true; +static bool prm_stored_procedure_uds_default = true; +static unsigned int prm_stored_procedure_uds_flag = 0; bool PRM_ALLOW_TRUNCATED_STRING = false; static bool prm_allow_truncated_string_default = false; @@ -3548,7 +3558,7 @@ SYSPRM_PARAM prm_Def[] = { (DUP_PRM_FUNC) NULL}, {PRM_ID_ORACLE_STYLE_EMPTY_STRING, PRM_NAME_ORACLE_STYLE_EMPTY_STRING, - (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_FOR_QRY_STRING | PRM_FORCE_SERVER), + (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_FOR_QRY_STRING | PRM_FORCE_SERVER | PRM_FOR_PL_CONTEXT), PRM_BOOLEAN, &prm_oracle_style_empty_string_flag, (void *) &prm_oracle_style_empty_string_default, @@ -3604,7 +3614,7 @@ SYSPRM_PARAM prm_Def[] = { (DUP_PRM_FUNC) NULL}, {PRM_ID_COMPAT_NUMERIC_DIVISION_SCALE, PRM_NAME_COMPAT_NUMERIC_DIVISION_SCALE, - (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_USER_CHANGE | PRM_FOR_SESSION | PRM_FOR_HA_CONTEXT), + (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_USER_CHANGE | PRM_FOR_SESSION | PRM_FOR_HA_CONTEXT | PRM_FOR_PL_CONTEXT), PRM_BOOLEAN, &prm_compat_numeric_division_scale_flag, (void *) &prm_compat_numeric_division_scale_default, @@ -3626,7 +3636,7 @@ SYSPRM_PARAM prm_Def[] = { (DUP_PRM_FUNC) NULL}, {PRM_ID_AUTO_RESTART_SERVER, PRM_NAME_AUTO_RESTART_SERVER, - (PRM_FOR_CLIENT | PRM_USER_CHANGE), + (PRM_FOR_SERVER | PRM_USER_CHANGE), PRM_BOOLEAN, &prm_auto_restart_server_flag, (void *) &prm_auto_restart_server_default, @@ -4665,7 +4675,7 @@ SYSPRM_PARAM prm_Def[] = { (DUP_PRM_FUNC) NULL}, {PRM_ID_INTL_NUMBER_LANG, PRM_NAME_INTL_NUMBER_LANG, - (PRM_FOR_CLIENT | PRM_USER_CHANGE | PRM_FOR_SESSION | PRM_FOR_QRY_STRING | PRM_FOR_HA_CONTEXT), + (PRM_FOR_CLIENT | PRM_USER_CHANGE | PRM_FOR_SESSION | PRM_FOR_QRY_STRING | PRM_FOR_HA_CONTEXT | PRM_FOR_PL_CONTEXT), PRM_STRING, &prm_intl_number_lang_flag, (void *) &prm_intl_number_lang_default, @@ -4676,7 +4686,7 @@ SYSPRM_PARAM prm_Def[] = { (DUP_PRM_FUNC) NULL}, {PRM_ID_INTL_DATE_LANG, PRM_NAME_INTL_DATE_LANG, - (PRM_FOR_CLIENT | PRM_USER_CHANGE | PRM_FOR_SESSION | PRM_FOR_QRY_STRING | PRM_FOR_HA_CONTEXT), + (PRM_FOR_CLIENT | PRM_USER_CHANGE | PRM_FOR_SESSION | PRM_FOR_QRY_STRING | PRM_FOR_HA_CONTEXT | PRM_FOR_PL_CONTEXT), PRM_STRING, &prm_intl_date_lang_flag, (void *) &prm_intl_date_lang_default, @@ -4817,7 +4827,7 @@ SYSPRM_PARAM prm_Def[] = { (DUP_PRM_FUNC) NULL}, {PRM_ID_INTL_COLLATION, PRM_NAME_INTL_COLLATION, - (PRM_FOR_CLIENT | PRM_FOR_SESSION | PRM_USER_CHANGE | PRM_FOR_HA_CONTEXT), + (PRM_FOR_CLIENT | PRM_FOR_SESSION | PRM_USER_CHANGE | PRM_FOR_HA_CONTEXT | PRM_FOR_PL_CONTEXT), PRM_STRING, &prm_intl_collation_flag, (void *) &prm_intl_collation_default, @@ -5311,7 +5321,8 @@ SYSPRM_PARAM prm_Def[] = { (DUP_PRM_FUNC) NULL}, {PRM_ID_TIMEZONE, PRM_NAME_TIMEZONE, - (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_FOR_SESSION | PRM_USER_CHANGE | PRM_FOR_QRY_STRING | PRM_FOR_HA_CONTEXT), + (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_FOR_SESSION | PRM_USER_CHANGE | PRM_FOR_QRY_STRING | PRM_FOR_HA_CONTEXT | + PRM_FOR_PL_CONTEXT), PRM_STRING, &prm_timezone_flag, (void *) &prm_timezone_default, @@ -6025,33 +6036,33 @@ SYSPRM_PARAM prm_Def[] = { (DUP_PRM_FUNC) NULL}, {PRM_ID_JAVA_STORED_PROCEDURE, PRM_NAME_JAVA_STORED_PROCEDURE, - (PRM_FOR_SERVER), + (PRM_FOR_SERVER | PRM_HIDDEN), PRM_BOOLEAN, - &prm_java_stored_procedure_flag, - (void *) &prm_java_stored_procedure_default, - (void *) &PRM_JAVA_STORED_PROCEDURE, + &prm_stored_procedure_flag, + (void *) &prm_stored_procedure_default, + (void *) &PRM_STORED_PROCEDURE, (void *) NULL, (void *) NULL, (char *) NULL, (DUP_PRM_FUNC) NULL, (DUP_PRM_FUNC) NULL}, {PRM_ID_JAVA_STORED_PROCEDURE_PORT, PRM_NAME_JAVA_STORED_PROCEDURE_PORT, - (PRM_FOR_SERVER), + (PRM_FOR_SERVER | PRM_HIDDEN), PRM_INTEGER, - &prm_java_stored_procedure_port_flag, - (void *) &prm_java_stored_procedure_port_default, - (void *) &PRM_JAVA_STORED_PROCEDURE_PORT, - (void *) &prm_java_stored_procedure_port_upper, (void *) &prm_java_stored_procedure_port_lower, + &prm_stored_procedure_port_flag, + (void *) &prm_stored_procedure_port_default, + (void *) &PRM_STORED_PROCEDURE_PORT, + (void *) &prm_stored_procedure_port_upper, (void *) &prm_stored_procedure_port_lower, (char *) NULL, (DUP_PRM_FUNC) NULL, (DUP_PRM_FUNC) NULL}, - {PRM_ID_JAVA_STORED_PROCEDURE_JVM_OPTIONS, + {PRM_ID_STORED_PROCEDURE_JVM_OPTIONS, PRM_NAME_JAVA_STORED_PROCEDURE_JVM_OPTIONS, - (PRM_FOR_SERVER), + (PRM_FOR_SERVER | PRM_HIDDEN), PRM_STRING, - &prm_java_stored_procedure_jvm_options_flag, - (void *) &prm_java_stored_procedure_jvm_options_default, - (void *) &PRM_JAVA_STORED_PROCEDURE_JVM_OPTIONS, + &prm_stored_procedure_jvm_options_flag, + (void *) &prm_stored_procedure_jvm_options_default, + (void *) &PRM_STORED_PROCEDURE_JVM_OPTIONS, (void *) NULL, (void *) NULL, (char *) NULL, (DUP_PRM_FUNC) NULL, @@ -6060,20 +6071,20 @@ SYSPRM_PARAM prm_Def[] = { PRM_NAME_JAVA_STORED_PROCEDURE_DEBUG, (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_HIDDEN), PRM_INTEGER, - &prm_java_stored_procedure_debug_flag, - (void *) &prm_java_stored_procedure_debug_default, - (void *) &PRM_JAVA_STORED_PROCEDURE_DEBUG, + &prm_stored_procedure_debug_flag, + (void *) &prm_stored_procedure_debug_default, + (void *) &PRM_STORED_PROCEDURE_DEBUG, (void *) NULL, (void *) NULL, (char *) NULL, (DUP_PRM_FUNC) NULL, (DUP_PRM_FUNC) NULL}, {PRM_ID_JAVA_STORED_PROCEDURE_UDS, PRM_NAME_JAVA_STORED_PROCEDURE_UDS, - (PRM_FOR_SERVER), + (PRM_FOR_SERVER | PRM_HIDDEN), PRM_BOOLEAN, - &prm_java_stored_procedure_uds_flag, - (void *) &prm_java_stored_procedure_uds_default, - (void *) &PRM_JAVA_STORED_PROCEDURE_UDS, + &prm_stored_procedure_uds_flag, + (void *) &prm_stored_procedure_uds_default, + (void *) &PRM_STORED_PROCEDURE_UDS, (void *) NULL, (void *) NULL, (char *) NULL, (DUP_PRM_FUNC) NULL, @@ -6277,7 +6288,7 @@ SYSPRM_PARAM prm_Def[] = { (DUP_PRM_FUNC) NULL}, {PRM_ID_ORACLE_COMPAT_NUMBER_BEHAVIOR, PRM_NAME_ORACLE_COMPAT_NUMBER_BEHAVIOR, - (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_FORCE_SERVER), + (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_FORCE_SERVER | PRM_FOR_PL_CONTEXT), PRM_BOOLEAN, &prm_oracle_compat_number_behavior_flag, (void *) &prm_oracle_compat_number_behavior_default, @@ -6448,6 +6459,61 @@ SYSPRM_PARAM prm_Def[] = { (void *) &prm_max_subquery_cache_size_lower, (char *) NULL, (DUP_PRM_FUNC) NULL, + (DUP_PRM_FUNC) NULL}, + {PRM_ID_STORED_PROCEDURE, + PRM_NAME_STORED_PROCEDURE, + (PRM_FOR_SERVER), + PRM_BOOLEAN, + &prm_stored_procedure_flag, + (void *) &prm_stored_procedure_default, + (void *) &PRM_STORED_PROCEDURE, + (void *) NULL, (void *) NULL, + (char *) NULL, + (DUP_PRM_FUNC) NULL, + (DUP_PRM_FUNC) NULL}, + {PRM_ID_STORED_PROCEDURE_PORT, + PRM_NAME_STORED_PROCEDURE_PORT, + (PRM_FOR_SERVER), + PRM_INTEGER, + &prm_stored_procedure_port_flag, + (void *) &prm_stored_procedure_port_default, + (void *) &PRM_STORED_PROCEDURE_PORT, + (void *) &prm_stored_procedure_port_upper, (void *) &prm_stored_procedure_port_lower, + (char *) NULL, + (DUP_PRM_FUNC) NULL, + (DUP_PRM_FUNC) NULL}, + {PRM_ID_STORED_PROCEDURE_JVM_OPTIONS, + PRM_NAME_STORED_PROCEDURE_JVM_OPTIONS, + (PRM_FOR_SERVER), + PRM_STRING, + &prm_stored_procedure_jvm_options_flag, + (void *) &prm_stored_procedure_jvm_options_default, + (void *) &PRM_STORED_PROCEDURE_JVM_OPTIONS, + (void *) NULL, (void *) NULL, + (char *) NULL, + (DUP_PRM_FUNC) NULL, + (DUP_PRM_FUNC) NULL}, + {PRM_ID_STORED_PROCEDURE_DEBUG, + PRM_NAME_STORED_PROCEDURE_DEBUG, + (PRM_FOR_CLIENT | PRM_FOR_SERVER | PRM_HIDDEN), + PRM_INTEGER, + &prm_stored_procedure_debug_flag, + (void *) &prm_stored_procedure_debug_default, + (void *) &PRM_STORED_PROCEDURE_DEBUG, + (void *) NULL, (void *) NULL, + (char *) NULL, + (DUP_PRM_FUNC) NULL, + (DUP_PRM_FUNC) NULL}, + {PRM_ID_STORED_PROCEDURE_UDS, + PRM_NAME_STORED_PROCEDURE_UDS, + (PRM_FOR_SERVER), + PRM_BOOLEAN, + &prm_stored_procedure_uds_flag, + (void *) &prm_stored_procedure_uds_default, + (void *) &PRM_STORED_PROCEDURE_UDS, + (void *) NULL, (void *) NULL, + (char *) NULL, + (DUP_PRM_FUNC) NULL, (DUP_PRM_FUNC) NULL} }; @@ -7450,7 +7516,7 @@ prm_load_by_section (INI_TABLE * ini, const char *section, bool ignore_section, } } - if (strcmp (section, "common") == 0 && strcmp (prm->name, PRM_NAME_JAVA_STORED_PROCEDURE_PORT) == 0) + if (strcmp (section, "common") == 0 && strcmp (prm->name, PRM_NAME_STORED_PROCEDURE_PORT) == 0) { error = PRM_ERR_CANNOT_CHANGE; prm_report_bad_entry (key + sec_len, ini->lineno[i], error, file); @@ -9204,6 +9270,53 @@ xsysprm_dump_server_parameters (FILE * outfp) { sysprm_dump_parameters (outfp); } + +/* + * xsysprm_get_pl_context_parameters () - obtain values for parameters + * marked as PRM_FOR_PL_CONTEXT + * + * return : list of values + * + */ +SYSPRM_ASSIGN_VALUE * +xsysprm_get_pl_context_parameters (void) +{ + SYSPRM_ASSIGN_VALUE *pl_ctx_values = NULL, *last_assign = NULL; + SYSPRM_PARAM *prm = NULL; + int i; + + for (i = 0; i < NUM_PRM; i++) + { + prm = GET_PRM (i); + if (PRM_IS_FOR_PL_CONTEXT (prm->static_flag)) + { + SYSPRM_ASSIGN_VALUE *change_val = (SYSPRM_ASSIGN_VALUE *) malloc (sizeof (SYSPRM_ASSIGN_VALUE)); + if (change_val == NULL) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (SYSPRM_ASSIGN_VALUE)); + goto cleanup; + } + change_val->prm_id = (PARAM_ID) i; + change_val->next = NULL; + sysprm_set_sysprm_value_from_parameter (&change_val->value, prm); + if (pl_ctx_values != NULL) + { + last_assign->next = change_val; + last_assign = change_val; + } + else + { + pl_ctx_values = last_assign = change_val; + } + } + } + + return pl_ctx_values; + +cleanup: + sysprm_free_assign_values (&pl_ctx_values); + return NULL; +} #endif /* !CS_MODE */ /* diff --git a/src/base/system_parameter.h b/src/base/system_parameter.h index 2ea92fcbe0c..354e0d348dc 100644 --- a/src/base/system_parameter.h +++ b/src/base/system_parameter.h @@ -452,6 +452,7 @@ enum param_id PRM_ID_JAVA_STORED_PROCEDURE_JVM_OPTIONS, PRM_ID_JAVA_STORED_PROCEDURE_DEBUG, PRM_ID_JAVA_STORED_PROCEDURE_UDS, + PRM_ID_ALLOW_TRUNCATED_STRING, PRM_ID_TB_DEFAULT_REUSE_OID, PRM_ID_USE_STAT_ESTIMATION, @@ -486,8 +487,14 @@ enum param_id PRM_ID_ENABLE_MEMORY_MONITORING, PRM_ID_MAX_SUBQUERY_CACHE_SIZE, + + PRM_ID_STORED_PROCEDURE, + PRM_ID_STORED_PROCEDURE_PORT, + PRM_ID_STORED_PROCEDURE_JVM_OPTIONS, + PRM_ID_STORED_PROCEDURE_DEBUG, + PRM_ID_STORED_PROCEDURE_UDS, /* change PRM_LAST_ID when adding new system parameters */ - PRM_LAST_ID = PRM_ID_MAX_SUBQUERY_CACHE_SIZE + PRM_LAST_ID = PRM_ID_STORED_PROCEDURE_UDS }; typedef enum param_id PARAM_ID; @@ -571,6 +578,7 @@ extern "C" #define PRM_HAS_TIME_UNIT(x) (x & PRM_TIME_UNIT) #define PRM_DIFFERENT_UNIT(x) (x & PRM_DIFFER_UNIT) #define PRM_IS_FOR_HA_CONTEXT(x) (x & PRM_FOR_HA_CONTEXT) +#define PRM_IS_FOR_PL_CONTEXT(x) (x & PRM_FOR_PL_CONTEXT) #define PRM_IS_GET_SERVER(x) (x & PRM_GET_SERVER) #define PRM_IS_DEPRECATED(x) (x & PRM_DEPRECATED) #define PRM_IS_OBSOLETED(x) (x & PRM_OBSOLETED) @@ -608,6 +616,8 @@ extern "C" * this flag only can be set if the parameter has PRM_FOR_CLIENT, * PRM_FOR_SERVER, and PRM_USER_CHANGE flags. */ +#define PRM_FOR_PL_CONTEXT 0x00020000 /* is for PL parameter */ + #define PRM_DEPRECATED 0x40000000 /* is deprecated */ #define PRM_OBSOLETED 0x80000000 /* is obsoleted */ @@ -729,6 +739,7 @@ extern "C" extern void xsysprm_obtain_server_parameters (SYSPRM_ASSIGN_VALUE * prm_values); extern SYSPRM_ASSIGN_VALUE *xsysprm_get_force_server_parameters (void); extern void xsysprm_dump_server_parameters (FILE * fp); + extern SYSPRM_ASSIGN_VALUE *xsysprm_get_pl_context_parameters (void); #endif /* !CS_MODE */ extern int sysprm_set_force (const char *pname, const char *pvalue); diff --git a/src/base/xserver_interface.h b/src/base/xserver_interface.h index 2ca0cbee9db..8fb3e8456e4 100644 --- a/src/base/xserver_interface.h +++ b/src/base/xserver_interface.h @@ -56,7 +56,6 @@ struct compile_context; struct xasl_cache_ent; struct xasl_stream; struct xasl_node_header; -struct method_sig_list; extern int xboot_initialize_server (const BOOT_CLIENT_CREDENTIAL * client_credential, BOOT_DB_PATH_INFO * db_path_info, bool db_overwrite, const char *file_addmore_vols, volatile DKNPAGES db_npages, @@ -294,11 +293,6 @@ extern bool xlogtb_does_active_user_exist (THREAD_ENTRY * thread_p, const char * extern int xlocator_demote_class_lock (THREAD_ENTRY * thread_p, const OID * class_oid, LOCK lock, LOCK * ex_lock); extern bool xtran_should_connection_reset (THREAD_ENTRY * thread_p, bool has_updated); extern int xsession_set_tran_auto_commit (THREAD_ENTRY * thread_p, bool auto_commit); - -// *INDENT-OFF* -extern int xmethod_invoke_fold_constants (THREAD_ENTRY * thread_p, const method_sig_list &sig_list, std::vector> &args, DB_VALUE &result); -// *INDENT-ON* - extern void xsynonym_remove_xasl_by_oid (THREAD_ENTRY * thread_p, OID * oidp); #endif /* _XSERVER_INTERFACE_H_ */ diff --git a/src/communication/network.h b/src/communication/network.h index fd4f7a118bd..8f5a80774ba 100644 --- a/src/communication/network.h +++ b/src/communication/network.h @@ -257,7 +257,7 @@ enum net_server_request NET_SERVER_VACUUM_DUMP, - NET_SERVER_METHOD_FOLD_CONSTANTS, + NET_SERVER_PL_CALL, NET_SERVER_SUPPLEMENT_STMT, diff --git a/src/communication/network_callback_cl.cpp b/src/communication/network_callback_cl.cpp new file mode 100644 index 00000000000..2b6c6574e48 --- /dev/null +++ b/src/communication/network_callback_cl.cpp @@ -0,0 +1,58 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "network_callback_cl.hpp" + +#include "network_interface_cl.h" /* net_client_send_data */ +#include "method_callback.hpp" + +static unsigned int xs_conn_info [METHOD_MAX_RECURSION_DEPTH + 1]; + +std::queue & +xs_get_data_queue () +{ + return cubmethod::get_callback_handler()->get_data_queue (); +} + +#if defined (CS_MODE) +void +xs_set_conn_info (int idx, unsigned int rc) +{ + xs_conn_info [idx] = rc; +} + +unsigned int +xs_get_conn_info (int idx) +{ + return xs_conn_info [idx]; +} + +int +xs_queue_send () +{ + int depth = tran_get_libcas_depth () - 1; + int rc = xs_get_conn_info (depth); + + assert (!xs_get_data_queue().empty()); + + cubmem::extensible_block &blk = xs_get_data_queue().front (); + int error = net_client_send_data (net_client_get_server_host(), rc, blk.get_ptr (), blk.get_size()); + xs_get_data_queue().pop (); + return error; +} +#endif \ No newline at end of file diff --git a/src/communication/network_callback_cl.hpp b/src/communication/network_callback_cl.hpp new file mode 100644 index 00000000000..373d121e8e3 --- /dev/null +++ b/src/communication/network_callback_cl.hpp @@ -0,0 +1,59 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _NETWORK_CALLBACK_CL_HPP_ +#define _NETWORK_CALLBACK_CL_HPP_ + +#include +#include + +#include "thread_compat.hpp" +#include "mem_block.hpp" /* cubmem::block */ +#include "packer.hpp" /* packing_packer */ + +#if defined (CS_MODE) +void xs_set_conn_info (int idx, unsigned int rc); +unsigned int xs_get_conn_info (int idx); +int xs_queue_send (); +#endif + +std::queue &xs_get_data_queue (); + +template +int xs_pack_and_queue (Args &&... args) +{ + packing_packer packer; + cubmem::extensible_block eb; + packer.set_buffer_and_pack_all (eb, std::forward (args)...); + eb.extend_to (packer.get_current_size ()); // ensure eb.get_size () == packer.get_current_size () + + xs_get_data_queue().push (std::move (eb)); + return NO_ERROR; +} + +template +int xs_send_queue (Args &&... args) +{ + xs_pack_and_queue (std::forward (args)...); +#if defined (CS_MODE) + xs_queue_send (); +#endif + return NO_ERROR; +} + +#endif // _NETWORK_CALLBACK_CL_HPP_ diff --git a/src/communication/network_callback_sr.cpp b/src/communication/network_callback_sr.cpp new file mode 100644 index 00000000000..54956b8c59c --- /dev/null +++ b/src/communication/network_callback_sr.cpp @@ -0,0 +1,106 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "network_callback_sr.hpp" + +#include "network.h" /* METHOD_CALL */ +#include "network_interface_sr.h" /* xs_receive_data_from_client() */ +#include "object_representation.h" /* OR_ */ +#include "server_support.h" /* css_send_reply_and_data_to_client(), css_get_comm_request_id() */ + +#if !defined (SERVER_MODE) +#include "query_method.hpp" +#include "method_callback.hpp" +#endif + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" + +#if defined (SERVER_MODE) +int xs_callback_send (cubthread::entry *thread_p, const cubmem::extensible_block &mem) +{ + OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply; + char *reply = OR_ALIGNED_BUF_START (a_reply); + + /* pack headers */ + char *ptr = or_pack_int (reply, (int) METHOD_CALL); + ptr = or_pack_int (ptr, (int) mem.get_size ()); + +#if !defined(NDEBUG) + /* suppress valgrind UMW error */ + memset (ptr, 0, OR_ALIGNED_BUF_SIZE (a_reply) - (ptr - reply)); +#endif + + if (thread_p == NULL || thread_p->conn_entry == NULL) + { + return ER_FAILED; + } + + /* send */ + unsigned int rid = css_get_comm_request_id (thread_p); + return css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), + (char * )mem.get_read_ptr(), (int) mem.get_size ()); +} + +int xs_callback_receive (cubthread::entry *thread_p, const xs_callback_func &func) +{ + cubmem::block buffer (0, nullptr); + + int error = xs_receive_data_from_client (thread_p, &buffer.ptr, (int *) &buffer.dim); + if (error == NO_ERROR && er_errid () == NO_ERROR) + { + error = func (buffer); + } + else + { + if (error == NO_ERROR) + { + error = er_errid (); // ER_SP_TOO_MANY_NESTED_CALL, ER_INTERRUPTED... (interrupt reasons) + } + } + + free_and_init (buffer.ptr); + return error; +} +#else +static std::queue & +xs_get_data_queue_from_cl () +{ + return cubmethod::get_callback_handler()->get_data_queue (); +} + +int xs_callback_send (cubthread::entry *thread_p, const cubmem::extensible_block &ext_blk) +{ + packing_unpacker unpacker (ext_blk.get_read_ptr (), ext_blk.get_size ()); + return method_dispatch (unpacker); +} + +int xs_callback_receive (cubthread::entry *thread_p, const xs_callback_func &func) +{ + std::queue &queue = xs_get_data_queue_from_cl (); + + assert (!queue.empty()); + + cubmem::extensible_block &blk = queue.front (); + cubmem::block buffer (blk.get_size(), blk.get_ptr()); + int error = func (buffer); + + queue.pop (); + return error; +} +#endif diff --git a/src/communication/network_callback_sr.hpp b/src/communication/network_callback_sr.hpp new file mode 100644 index 00000000000..b4de6063621 --- /dev/null +++ b/src/communication/network_callback_sr.hpp @@ -0,0 +1,81 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _NETWORK_CALLBACK_SR_HPP_ +#define _NETWORK_CALLBACK_SR_HPP_ + +#include +#include + +#include "error_code.h" +#include "thread_compat.hpp" +#include "mem_block.hpp" /* cubmem::block */ +#include "packer.hpp" /* packing_packer */ + +////////////////////////////////////////////////////////////////////////// +// Packing data +////////////////////////////////////////////////////////////////////////// +template +cubmem::extensible_block pack_data (Args &&... args) +{ + packing_packer packer; + cubmem::extensible_block eb; + packer.set_buffer_and_pack_all (eb, std::forward (args)...); + return eb; +} + +template +cubmem::block pack_data_block (Args &&... args) +{ + packing_packer packer; + cubmem::extensible_block eb; + packer.set_buffer_and_pack_all (eb, std::forward (args)...); + cubmem::block b (packer.get_current_size(), eb.release_ptr()); + return b; +} + +////////////////////////////////////////////////////////////////////////// +// Send/Receive +////////////////////////////////////////////////////////////////////////// +using xs_callback_func = std::function ; + +int xs_callback_receive (cubthread::entry *thread_p, const xs_callback_func &func); +int xs_callback_send (cubthread::entry *thread_p, const cubmem::extensible_block &mem); + +template +int xs_callback_send_args (cubthread::entry *thread_p, Args &&... args) +{ + const cubmem::extensible_block b = std::move (pack_data (std::forward (args)...)); + return xs_callback_send (thread_p, b); +} + +template +int xs_callback_send_and_receive (cubthread::entry *thread_p, const xs_callback_func &func, Args &&... args) +{ + int error_code = NO_ERROR; + + error_code = xs_callback_send_args (thread_p, std::forward (args)...); + if (error_code != NO_ERROR) + { + return error_code; + } + + return xs_callback_receive (thread_p, func); +} + +#endif // _NETWORK_CALLBACK_SR_HPP_ diff --git a/src/communication/network_cl.c b/src/communication/network_cl.c index b23805c3fcb..72a0c89afd6 100644 --- a/src/communication/network_cl.c +++ b/src/communication/network_cl.c @@ -48,7 +48,8 @@ #include "environment_variable.h" #include "boot_cl.h" #include "query_method.hpp" -#include "method_def.hpp" +#include "method_callback.hpp" + #include "release_string.h" #include "log_comm.h" #include "file_io.h" @@ -1714,6 +1715,15 @@ net_client_request_with_callback (int request, char *argbuf, int argsize, char * } while (server_request != END_CALLBACK && server_request != QUERY_END); + /* + * delete deferred query handlers during PL execution + * TODO: move it to proper place + */ + if (!tran_is_in_libcas ()) + { + cubmethod::get_callback_handler ()->free_deferred_query_handler (); + } + if (histo_is_collecting ()) { int recevied = replysize @@ -1907,6 +1917,15 @@ net_client_request_method_callback (int request, char *argbuf, int argsize, char } while (server_request != END_CALLBACK); + /* + * delete deferred query handlers during PL execution + * TODO: move it to proper place + */ + if (!tran_is_in_libcas ()) + { + cubmethod::get_callback_handler ()->free_deferred_query_handler (); + } + if (histo_is_collecting ()) { int recevied = replysize + (replydatasize_ptr ? *replydatasize_ptr : 0); diff --git a/src/communication/network_common.cpp b/src/communication/network_common.cpp index d424dbbb0e3..104a983cb0e 100644 --- a/src/communication/network_common.cpp +++ b/src/communication/network_common.cpp @@ -218,6 +218,8 @@ const char *net_server_request_name[NET_SERVER_REQUEST_END] = "NET_SERVER_LD_UPDATE_STATS", "NET_SERVER_VACUUM_DUMP", + "NET_SERVER_PL_CALL", + "NET_SERVER_SUPPLEMENT_STMT", "NET_SERVER_CDC_START_SESSION", diff --git a/src/communication/network_interface_cl.c b/src/communication/network_interface_cl.c index f7a698641c4..8e4c74779a1 100644 --- a/src/communication/network_interface_cl.c +++ b/src/communication/network_interface_cl.c @@ -46,7 +46,7 @@ #include "locator_sr.h" #include "query_executor.h" #include "transaction_sr.h" -#include "jsp_sr.h" +#include "pl_sr.h" #include "vacuum.h" #include "serial.h" #endif /* defined (SA_MODE) */ @@ -67,15 +67,20 @@ #include "db_query.h" #include "dbtype.h" #include "compile_context.h" + #if defined (SA_MODE) #include "thread_manager.hpp" +#include "pl_compile_handler.hpp" +#include "pl_executor.hpp" #endif // SA_MODE + #include "xasl.h" #include "lob_locator.hpp" #include "crypt_opfunc.h" #include "method_error.hpp" #include "message_catalog.h" #include "utility.h" +#include "sp_constants.hpp" /* * Use db_clear_private_heap instead of db_destroy_private_heap @@ -9083,14 +9088,14 @@ sysprm_dump_server_parameters (FILE * outfp) } /* - * jsp_get_server_port - + * pl_get_server_port - * * return: * * NOTE: */ int -jsp_get_server_port (void) +pl_get_server_port (void) { #if defined(CS_MODE) int req_error; @@ -9115,7 +9120,7 @@ jsp_get_server_port (void) #else /* CS_MODE */ int port; THREAD_ENTRY *thread_p = enter_server (); - port = jsp_server_port_from_info (); + port = pl_server_port_from_info (); exit_server (*thread_p); return port; #endif /* !CS_MODE */ @@ -10965,23 +10970,23 @@ loaddb_update_stats (bool verbose) } int -method_invoke_fold_constants (const method_sig_list & sig_list, - std::vector < std::reference_wrapper < DB_VALUE >> &args, DB_VALUE & result) +pl_call (const cubpl::pl_signature & sig, const std::vector < std::reference_wrapper < DB_VALUE >> &args, + std::vector < DB_VALUE > &out_args, DB_VALUE & result) { + int req_error = NO_ERROR; #if defined(CS_MODE) char *data_reply = NULL; int data_reply_size = 0; - int req_error = NO_ERROR; packing_packer packer; cubmem::extensible_block eb; - packer.set_buffer_and_pack_all (eb, sig_list, args); + packer.set_buffer_and_pack_all (eb, sig, args); { OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply; char *reply = OR_ALIGNED_BUF_START (a_reply); - req_error = net_client_request_method_callback (NET_SERVER_METHOD_FOLD_CONSTANTS, eb.get_ptr (), + req_error = net_client_request_method_callback (NET_SERVER_PL_CALL, eb.get_ptr (), (int) packer.get_current_size (), reply, OR_ALIGNED_BUF_SIZE (a_reply), &data_reply, &data_reply_size); if (req_error != NO_ERROR) @@ -10999,29 +11004,10 @@ method_invoke_fold_constants (const method_sig_list & sig_list, if (data_reply != NULL) { packing_unpacker unpacker (data_reply, (size_t) data_reply_size); - // *INDENT-OFF* - std::vector out_args; - // *INDENT-ON* - unpacker.unpack_all (result, out_args); - - method_sig_node *sig = sig_list.method_sig; - for (int i = 0; i < sig->num_method_args; i++) + if (data_reply_size > 0) { - if (sig->arg_info.arg_mode[i] == METHOD_ARG_MODE_IN) - { - continue; - } - - int pos = sig->method_arg_pos[i]; - - DB_VALUE & arg = args[pos]; - DB_VALUE & out_arg = out_args[pos]; - - db_value_clear (&arg); - db_value_clone (&out_arg, &arg); + unpacker.unpack_all (result, out_args); } - - pr_clear_value_vector (out_args); } else { @@ -11035,8 +11021,11 @@ method_invoke_fold_constants (const method_sig_list & sig_list, packing_unpacker unpacker (data_reply, (size_t) data_reply_size); int error_code; std::string error_msg; - unpacker.unpack_all (error_code, error_msg); - cubmethod::handle_method_error (error_code, error_msg); + if (data_reply_size > 0) + { + unpacker.unpack_all (error_code, error_msg); + cubmethod::handle_method_error (error_code, error_msg); + } } if (data_reply != NULL) @@ -11045,39 +11034,63 @@ method_invoke_fold_constants (const method_sig_list & sig_list, } return req_error; -#else /* CS_MODE */ - int error_code = NO_ERROR; - +#else + packing_packer packer; + cubmem::extensible_block eb; THREAD_ENTRY *thread_p = enter_server (); - error_code = xmethod_invoke_fold_constants (thread_p, sig_list, args, result); + { + DB_VALUE ret_value; + cubpl::executor executor ((cubpl::pl_signature &) sig); + req_error = executor.fetch_args_peek (args); + if (req_error == NO_ERROR) + { + req_error = executor.execute (ret_value); + } - cubmethod::runtime_context * rctx = cubmethod::get_rctx (thread_p); - assert (rctx); + if (req_error == NO_ERROR) + { + /* 3) pack */ + packer.set_buffer_and_pack_all (eb, ret_value, executor.get_out_args ()); + } + else + { + std::string err_msg = executor.get_stack ()->get_error_message (); + if (err_msg.empty () && req_error != ER_SP_EXECUTE_ERROR) + { + err_msg.assign (er_msg ()); + } - cubmethod::method_invoke_group * top_on_stack = rctx->top_stack (); - assert (top_on_stack); + if (req_error != ER_SM_INVALID_METHOD_ENV) /* FIXME: error possibly occured in builtin method, It should be handled at CAS */ + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_EXECUTE_ERROR, 1, err_msg); + } - if (error_code != NO_ERROR) - { - if (rctx->is_interrupted ()) - { - rctx->set_local_error_for_interrupt (); - } - else if (error_code != ER_SM_INVALID_METHOD_ENV) /* FIXME: error possibly occured in builtin method, It should be handled at CAS */ - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_EXECUTE_ERROR, 1, top_on_stack->get_error_msg ().c_str ()); - } - } + packer.set_buffer_and_pack_all (eb, er_errid (), err_msg); + } - top_on_stack->reset (true); - top_on_stack->end (); - rctx->pop_stack (thread_p, top_on_stack); + db_value_clear (&ret_value); + } exit_server (*thread_p); - return error_code; -#endif /* !CS_MODE */ + // unpack after exit_server (): ownership of the private allocated objects should be out of server mode + packing_unpacker unpacker (eb.get_ptr (), (size_t) packer.get_current_size ()); + if (req_error == NO_ERROR) + { + db_make_null (&result); + unpacker.unpack_all (result, out_args); + } + else + { + int error_code; + std::string error_msg; + unpacker.unpack_all (error_code, error_msg); + cubmethod::handle_method_error (error_code, error_msg); + } + + return req_error; +#endif } /* @@ -11306,10 +11319,10 @@ flashback_get_loginfo (int trid, char *user, OID * classlist, int num_class, LOG } int -plcsql_transfer_file (const std::string & input_file, const bool & verbose, PLCSQL_COMPILE_INFO & compile_info) +plcsql_transfer_file (const PLCSQL_COMPILE_REQUEST & compile_request, PLCSQL_COMPILE_RESPONSE & compile_response) { + int req_error = NO_ERROR; #if defined(CS_MODE) - int rc = ER_FAILED; packing_packer packer; cubmem::extensible_block eb; char *ptr = NULL; @@ -11317,14 +11330,13 @@ plcsql_transfer_file (const std::string & input_file, const bool & verbose, PLCS char *data_reply = NULL; int data_reply_size = 0; - packer.set_buffer_and_pack_all (eb, verbose, input_file); + packer.set_buffer_and_pack_all (eb, compile_request); OR_ALIGNED_BUF (3 * OR_INT_SIZE) a_reply; char *reply = OR_ALIGNED_BUF_START (a_reply); - int req_error = net_client_request_method_callback (NET_SERVER_PLCSQL_TRANSFER_FILE, eb.get_ptr (), - (int) packer.get_current_size (), - reply, OR_ALIGNED_BUF_SIZE (a_reply), &data_reply, - &data_reply_size); + req_error = net_client_request_method_callback (NET_SERVER_PLCSQL_TRANSFER_FILE, eb.get_ptr (), + (int) packer.get_current_size (), + reply, OR_ALIGNED_BUF_SIZE (a_reply), &data_reply, &data_reply_size); if (req_error != NO_ERROR) { goto error; @@ -11340,16 +11352,29 @@ plcsql_transfer_file (const std::string & input_file, const bool & verbose, PLCS if (data_reply != NULL) { packing_unpacker unpacker (data_reply, (size_t) data_reply_size); - unpacker.unpack_all (compile_info); - rc = NO_ERROR; + if (data_reply_size > 0) + { + unpacker.unpack_all (compile_response); + } } error: - // TODO error handling if (req_error != NO_ERROR) { - // TODO: er_set (...): set proper error - rc = req_error; + if (data_reply != NULL) + { + packing_unpacker unpacker (data_reply, (size_t) data_reply_size); + if (data_reply_size > 0) + { + unpacker.unpack_all (compile_response); + } + } + + if (compile_response.err_code == NO_ERROR) + { + compile_response.err_code = (er_errid () != NO_ERROR) ? er_errid () : req_error; + compile_response.err_msg = er_msg ()? er_msg () : "unknown error"; + } } if (data_reply != NULL) @@ -11357,9 +11382,36 @@ plcsql_transfer_file (const std::string & input_file, const bool & verbose, PLCS free_and_init (data_reply); } - return rc; + return req_error; #else /* CS_MODE */ - return NO_ERROR; + int success = ER_FAILED; + + cubmem::extensible_block eb; + THREAD_ENTRY *thread_p = enter_server (); + + { + cubpl::compile_handler compile_handler; + success = compile_handler.compile (compile_request, eb); + } + + exit_server (*thread_p); + + // unpack after exit_server (): ownership of the private allocated objects should be out of server mode + if (success == NO_ERROR) + { + packing_unpacker unpacker (eb.get_ptr (), eb.get_size ()); + if (eb.get_size () > 0) + { + unpacker.unpack_all (compile_response); + } + } + else + { + compile_response.err_code = (er_errid () != NO_ERROR) ? er_errid () : success; + compile_response.err_msg = er_msg ()? er_msg () : "unknown error"; + } + + return success; #endif /* !CS_MODE */ } diff --git a/src/communication/network_interface_cl.h b/src/communication/network_interface_cl.h index 0e225077fa4..5b268d1872e 100644 --- a/src/communication/network_interface_cl.h +++ b/src/communication/network_interface_cl.h @@ -51,10 +51,11 @@ #include "parse_tree.h" #include "load_common.hpp" #include "timezone_lib_common.h" -#include "method_def.hpp" + #include "dynamic_array.h" #include "flashback_cl.h" -#include "method_compile_def.hpp" +#include "pl_struct_compile.hpp" +#include "pl_signature.hpp" #include "memory_monitor_common.hpp" // forward declarations @@ -299,7 +300,7 @@ extern int db_local_transaction_id (DB_VALUE * trid); extern int qp_get_server_info (PARSER_CONTEXT * parser, int server_info_bits); extern int locator_redistribute_partition_data (OID * class_oid, int no_oids, OID * oid_list); -extern int jsp_get_server_port (void); +extern int pl_get_server_port (void); extern int repl_log_get_append_lsa (LOG_LSA * lsa); extern int repl_set_info (REPL_INFO * repl_info); @@ -446,8 +447,6 @@ extern int loaddb_destroy (); extern int loaddb_interrupt (); extern int loaddb_update_stats (bool verbose); -extern int method_invoke_fold_constants (const method_sig_list & sig_list, - std::vector < std::reference_wrapper < DB_VALUE >> &args, DB_VALUE & result); extern int flashback_get_and_show_summary (dynamic_array * class_list, const char *user, time_t start_time, time_t end_time, FLASHBACK_SUMMARY_INFO_MAP * summary, OID ** oid_list, char **invalid_class, time_t * invalid_time); @@ -456,9 +455,11 @@ extern int flashback_get_loginfo (int trid, char *user, OID * classlist, int num int *invalid_class_idx); /* PL/CSQL */ -EXPORT_IMPORT extern int plcsql_transfer_file (const std::string & input_file, const bool & verbose, - PLCSQL_COMPILE_INFO & compile_info); - +EXPORT_IMPORT extern int plcsql_transfer_file (const PLCSQL_COMPILE_REQUEST & compile_request, + PLCSQL_COMPILE_RESPONSE & compile_response); +EXPORT_IMPORT extern int pl_call (const cubpl::pl_signature & sig, + const std::vector < std::reference_wrapper < DB_VALUE >> &args, + std::vector < DB_VALUE > &out_args, DB_VALUE & result); /* memmon */ extern int mmon_get_server_info (MMON_SERVER_INFO & server_info); diff --git a/src/communication/network_interface_sr.c b/src/communication/network_interface_sr.c index 5a2509aedb1..1f0ca0742d0 100644 --- a/src/communication/network_interface_sr.c +++ b/src/communication/network_interface_sr.c @@ -63,7 +63,7 @@ #include "statistics.h" #include "chartype.h" #include "heap_file.h" -#include "jsp_sr.h" +#include "pl_sr.h" #include "replication.h" #include "server_support.h" #include "connection_sr.h" @@ -86,11 +86,14 @@ #include "elo.h" #include "transaction_transient.hpp" #include "method_invoke_group.hpp" -#include "method_runtime_context.hpp" #include "log_manager.h" #include "crypt_opfunc.h" #include "flashback.h" -#include "method_compile.hpp" +#include "pl_struct_compile.hpp" +#include "pl_compile_handler.hpp" +#include "pl_session.hpp" +#include "pl_executor.hpp" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" @@ -160,8 +163,8 @@ stran_server_commit_internal (THREAD_ENTRY * thread_p, unsigned int rid, bool re state = xtran_server_commit (thread_p, retain_lock); - cubmethod::runtime_context * rctx = cubmethod::get_rctx (thread_p); - if (!rctx || rctx->is_running () == false || rctx->get_depth () == 0) + PL_SESSION *session = cubpl::get_session (); + if (!session || session->is_running () == false) { net_cleanup_server_queues (rid); } @@ -198,8 +201,8 @@ stran_server_abort_internal (THREAD_ENTRY * thread_p, unsigned int rid, bool * s state = xtran_server_abort (thread_p); - cubmethod::runtime_context * rctx = cubmethod::get_rctx (thread_p); - if (!rctx || rctx->is_running () == false || rctx->get_depth () == 0) + PL_SESSION *session = cubpl::get_session (); + if (!session || session->is_running () == false) { net_cleanup_server_queues (rid); } @@ -6647,50 +6650,6 @@ sct_check_rep_dir (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply)); } -/* - * xs_send_method_call_info_to_client - - * - * return: - * - * list_id(in): - * method_sig_list(in): - * - * NOTE: - */ -int -xs_send_method_call_info_to_client (THREAD_ENTRY * thread_p, qfile_list_id * list_id, method_sig_list * methsg_list) -{ - int length = 0; - char *databuf; - char *ptr; - unsigned int rid; - OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply; - char *reply = OR_ALIGNED_BUF_START (a_reply); - - rid = css_get_comm_request_id (thread_p); - length = or_listid_length ((void *) list_id); - length += or_method_sig_list_length ((void *) methsg_list); - ptr = or_pack_int (reply, (int) METHOD_CALL); - ptr = or_pack_int (ptr, length); - -#if !defined(NDEBUG) - /* suppress valgrind UMW error */ - memset (ptr, 0, OR_ALIGNED_BUF_SIZE (a_reply) - (ptr - reply)); -#endif - - databuf = (char *) db_private_alloc (thread_p, length); - if (databuf == NULL) - { - return ER_FAILED; - } - - ptr = or_pack_listid (databuf, (void *) list_id); - ptr = or_pack_method_sig_list (ptr, (void *) methsg_list); - css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), databuf, length); - db_private_free_and_init (thread_p, databuf); - return NO_ERROR; -} - /* * xs_receive_data_from_client - * @@ -8080,7 +8039,7 @@ stran_get_local_transaction_id (THREAD_ENTRY * thread_p, unsigned int rid, char } /* - * sjsp_get_server_port - + * spl_get_server_port - * * return: * @@ -8089,12 +8048,12 @@ stran_get_local_transaction_id (THREAD_ENTRY * thread_p, unsigned int rid, char * NOTE: */ void -sjsp_get_server_port (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen) +spl_get_server_port (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen) { OR_ALIGNED_BUF (OR_INT_SIZE) a_reply; char *reply = OR_ALIGNED_BUF_START (a_reply); - (void) or_pack_int (reply, jsp_server_port_from_info ()); + (void) or_pack_int (reply, pl_server_port_from_info ()); css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply)); } @@ -10547,6 +10506,84 @@ cdc_check_client_connection () } } +void +spl_call (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen) +{ + int error_code = NO_ERROR; + packing_unpacker unpacker (request, (size_t) reqlen); + + DB_VALUE ret_value; + db_make_null (&ret_value); + + /* 1) unpack arguments */ + cubpl::pl_signature sig; + std::vector < DB_VALUE > args; + unpacker.unpack_all (sig, args); + + std::vector < std::reference_wrapper < DB_VALUE >> ref_args (args.begin (), args.end ()); + + /* 2) invoke */ + cubpl::executor executor (sig); + error_code = executor.fetch_args_peek (ref_args); + if (error_code == NO_ERROR) + { + error_code = executor.execute (ret_value); + } + + packing_packer packer; + cubmem::extensible_block eb; + if (error_code == NO_ERROR) + { + /* 3) pack */ + packer.set_buffer_and_pack_all (eb, ret_value, executor.get_out_args ()); + } + else + { + std::string err_msg = executor.get_stack ()->get_error_message (); + if (err_msg.empty () && error_code != ER_SP_EXECUTE_ERROR) + { + err_msg.assign (er_msg ()); + } + + if (error_code != ER_SM_INVALID_METHOD_ENV) /* FIXME: error possibly occured in builtin method, It should be handled at CAS */ + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_EXECUTE_ERROR, 1, err_msg.c_str ()); + } + packer.set_buffer_and_pack_all (eb, er_errid (), err_msg); + (void) return_error_to_client (thread_p, rid); + } + + char *reply_data = eb.get_ptr (); + int reply_data_size = (int) packer.get_current_size (); + + OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply; + char *reply = OR_ALIGNED_BUF_START (a_reply); + char *ptr = or_pack_int (reply, (int) END_CALLBACK); + ptr = or_pack_int (ptr, reply_data_size); + ptr = or_pack_int (ptr, error_code); + + // clear + //if (top_on_stack) + // { + // top_on_stack->reset (true); + // top_on_stack->end (); + // } + + css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), reply_data, + reply_data_size); + +/* + if (top_on_stack) + { + rctx->pop_stack (thread_p, top_on_stack); + } +*/ + + pr_clear_value_vector (args); + db_value_clear (&ret_value); +} + +#if 0 void smethod_invoke_fold_constants (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen) { @@ -10593,7 +10630,7 @@ smethod_invoke_fold_constants (THREAD_ENTRY * thread_p, unsigned int rid, char * // *INDENT-ON* for (int i = 0; i < sig->num_method_args; i++) { - if (sig->arg_info.arg_mode[i] == METHOD_ARG_MODE_IN) + if (sig->arg_info->arg_mode[i] == METHOD_ARG_MODE_IN) { continue; } @@ -10669,6 +10706,7 @@ smethod_invoke_fold_constants (THREAD_ENTRY * thread_p, unsigned int rid, char * db_value_clear (&ret_value); sig_list.freemem (); } +#endif void scdc_start_session (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen) @@ -11282,23 +11320,16 @@ sflashback_get_loginfo (THREAD_ENTRY * thread_p, unsigned int rid, char *request void splcsql_transfer_file (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen) { - packing_unpacker unpacker (request, (size_t) reqlen); - - bool verbose; - std::string input_string; - unpacker.unpack_all (verbose, input_string); + int error = ER_FAILED; + PLCSQL_COMPILE_REQUEST compile_request; - cubmethod::runtime_context * ctx = NULL; - session_get_method_runtime_context (thread_p, ctx); + packing_unpacker unpacker (request, (size_t) reqlen); + unpacker.unpack_all (compile_request); - int error = ER_FAILED; cubmem::extensible_block ext_blk; - if (ctx) - { - error = cubmethod::invoke_compile (*thread_p, *ctx, input_string, verbose, ext_blk); - } + cubpl::compile_handler compile_handler; + error = compile_handler.compile (compile_request, ext_blk); - // Error code and is_ignored. OR_ALIGNED_BUF (3 * OR_INT_SIZE) a_reply; char *reply = OR_ALIGNED_BUF_START (a_reply); char *ptr = or_pack_int (reply, (int) END_CALLBACK); diff --git a/src/communication/network_interface_sr.h b/src/communication/network_interface_sr.h index 142478d99bc..4aba9050491 100644 --- a/src/communication/network_interface_sr.h +++ b/src/communication/network_interface_sr.h @@ -37,7 +37,6 @@ #include "thread_compat.hpp" // forward definitions -struct method_sig_list; struct qfile_list_id; extern TRAN_STATE return_error_to_client (THREAD_ENTRY * thread_p, unsigned int rid); @@ -151,8 +150,7 @@ extern void smnt_server_stop_stats (THREAD_ENTRY * thread_p, unsigned int rid, c extern void smnt_server_copy_stats (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void smnt_server_copy_global_stats (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void sct_check_rep_dir (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); -extern int xs_send_method_call_info_to_client (THREAD_ENTRY * thread_p, qfile_list_id * list_id, - method_sig_list * methsg_list); + extern int xs_receive_data_from_client (THREAD_ENTRY * thread_p, char **area, int *datasize); extern int xs_receive_data_from_client_with_timeout (THREAD_ENTRY * thread_p, char **area, int *datasize, int timeout); @@ -184,7 +182,7 @@ extern void sprm_server_get_force_parameters (THREAD_ENTRY * thread_p, unsigned extern void sprm_server_dump_parameters (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void shf_has_instance (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void stran_get_local_transaction_id (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); -extern void sjsp_get_server_port (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); +extern void spl_get_server_port (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void srepl_set_info (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void srepl_log_get_append_lsa (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void slocator_check_fk_validity (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); @@ -244,8 +242,6 @@ extern void sloaddb_interrupt (THREAD_ENTRY * thread_p, unsigned int rid, char * extern void sloaddb_update_stats (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void ssession_stop_attached_threads (void *session); -extern void smethod_invoke_fold_constants (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); - /* For CDC */ extern void slog_supplement_statement (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void scdc_start_session (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); @@ -258,8 +254,9 @@ extern void scdc_end_session (THREAD_ENTRY * thread_p, unsigned int rid, char *r extern void sflashback_get_summary (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); extern void sflashback_get_loginfo (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); -/* PL/CSQL */ +/* PL */ extern void splcsql_transfer_file (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); +extern void spl_call (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); /* memmon */ extern void smmon_get_server_info (THREAD_ENTRY * thread_p, unsigned int rid, char *request, int reqlen); diff --git a/src/communication/network_sr.c b/src/communication/network_sr.c index 0bfc923c854..765035dfba4 100644 --- a/src/communication/network_sr.c +++ b/src/communication/network_sr.c @@ -555,7 +555,7 @@ net_server_init (void) /* JSP */ req_p = &net_Requests[NET_SERVER_JSP_GET_SERVER_PORT]; req_p->action_attribute = IN_TRANSACTION; - req_p->processing_function = sjsp_get_server_port; + req_p->processing_function = spl_get_server_port; /* replication */ req_p = &net_Requests[NET_SERVER_REPL_INFO]; @@ -712,9 +712,9 @@ net_server_init (void) req_p = &net_Requests[NET_SERVER_VACUUM_DUMP]; req_p->processing_function = svacuum_dump; - req_p = &net_Requests[NET_SERVER_METHOD_FOLD_CONSTANTS]; + req_p = &net_Requests[NET_SERVER_PL_CALL]; req_p->action_attribute = IN_TRANSACTION; - req_p->processing_function = smethod_invoke_fold_constants; + req_p->processing_function = spl_call; req_p = &net_Requests[NET_SERVER_SUPPLEMENT_STMT]; req_p->processing_function = slog_supplement_statement; diff --git a/src/compat/db_admin.c b/src/compat/db_admin.c index 545c76fb707..823c495fcb1 100644 --- a/src/compat/db_admin.c +++ b/src/compat/db_admin.c @@ -56,7 +56,7 @@ #include "execute_schema.h" #include "network_interface_cl.h" #if defined(SA_MODE) -#include "jsp_sr.h" +#include "pl_sr.h" #endif /* SA_MODE */ #include "jsp_cl.h" #include "execute_statement.h" @@ -928,7 +928,7 @@ db_restart (const char *program, int print_version, const char *volume) install_static_methods (); #if !defined(WINDOWS) #if defined(SA_MODE) && (defined(LINUX) || defined(x86_SOLARIS)) - if (!jsp_jvm_is_loaded ()) + if (!pl_jvm_is_loaded ()) { prev_sigfpe_handler = os_set_signal_handler (SIGFPE, sigfpe_handler); } @@ -1811,6 +1811,39 @@ db_set_user_comment (DB_OBJECT * user, const char *comment) return (retval); } +/* + * db_get_object_type() - This returns database object type of given MOP + * return : DB_OBJECT_TYPE + * obj_(in) : an object + * + */ +// TODO: find better solution +DB_OBJECT_TYPE +db_get_object_type (MOP obj_) +{ + DB_OBJECT_TYPE ret_val = DB_OBJECT_UNKNOWN; + + assert (obj_->class_mop != NULL); + + OID *mop = WS_OID (obj_->class_mop); + if (OID_EQ (mop, WS_OID (sm_Root_class_mop))) + { + // table, view + ret_val = DB_OBJECT_CLASS; + } + else + { + // database object types except (v)class + MOP sp_class_mop = sm_find_class (CT_STORED_PROC_NAME); + if (sp_class_mop && OID_EQ (mop, WS_OID (sp_class_mop))) + { + ret_val = DB_OBJECT_PROCEDURE; + } + } + + return ret_val; +} + /* * db_grant() -This is the basic mechanism for passing permissions to other * users. The authorization type is one of the numeric values defined @@ -1827,18 +1860,62 @@ db_set_user_comment (DB_OBJECT * user, const char *comment) * */ int -db_grant (MOP user, MOP class_, AU_TYPE auth, int grant_option) +db_grant (MOP user, MOP obj_, AU_TYPE auth, int grant_option) { - int retval; + int retval = NO_ERROR; + DB_OBJECT_TYPE object_type; CHECK_CONNECT_ERROR (); - CHECK_2ARGS_ERROR (user, class_); + CHECK_2ARGS_ERROR (user, obj_); CHECK_MODIFICATION_ERROR (); - retval = do_check_partitioned_class (class_, CHECK_PARTITION_SUBS, NULL); + object_type = db_get_object_type (obj_); + if (object_type == DB_OBJECT_CLASS) + { + retval = do_check_partitioned_class (obj_, CHECK_PARTITION_SUBS, NULL); + } + if (!retval) { - retval = au_grant (user, class_, auth, (bool) grant_option); + retval = au_grant (object_type, user, obj_, auth, (bool) grant_option); + } + + return (retval); +} + +/* + * db_grant_object() -This is the basic mechanism for passing permissions to other + * users. The authorization type is one of the numeric values defined + * by the DB_AUTH enumeration. If more than one authorization is to + * be granted, the values in DB_AUTH can be combined using the C bitwise + * "or" operator |. Errors are likely if the currently logged in user + * was not the owner of the class and was not given the grant_option for + * the desired authorization types. + * return : error code + * object_type(in) : an object type + * user(in) : a user object + * obj_(in) : an object + * auth(in) : an authorization type + * grant_option(in) : true if the grant option is to be added + * + */ +int +db_grant_object (DB_OBJECT_TYPE object_type, DB_OBJECT * user, DB_OBJECT * obj_, DB_AUTH auth, int grant_option) +{ + int retval = NO_ERROR; + + CHECK_CONNECT_ERROR (); + CHECK_2ARGS_ERROR (user, obj_); + CHECK_MODIFICATION_ERROR (); + + if (object_type == DB_OBJECT_CLASS) + { + retval = do_check_partitioned_class (obj_, CHECK_PARTITION_SUBS, NULL); + } + + if (!retval) + { + retval = au_grant (object_type, user, obj_, auth, (bool) grant_option); } return (retval); @@ -1854,18 +1931,56 @@ db_grant (MOP user, MOP class_, AU_TYPE auth, int grant_option) * */ int -db_revoke (MOP user, MOP class_mop, AU_TYPE auth) +db_revoke (MOP user, MOP obj_, AU_TYPE auth) { - int retval; + int retval = NO_ERROR; + DB_OBJECT_TYPE object_type; + + CHECK_CONNECT_ERROR (); + CHECK_2ARGS_ERROR (user, obj_); + CHECK_MODIFICATION_ERROR (); + + object_type = db_get_object_type (obj_); + if (object_type == DB_OBJECT_CLASS) + { + retval = do_check_partitioned_class (obj_, CHECK_PARTITION_SUBS, NULL); + } + + if (!retval) + { + retval = au_revoke (object_type, user, obj_, auth, NULL); + } + + return (retval); +} + +/* + * db_revoke_object() - This is the basic mechanism for revoking previously granted + * authorizations. A prior authorization must have been made. + * returns : error code + * object_type(in) : an object type + * user(in) : a user object + * class_mop(in): a class object + * auth(in) : the authorization type(s) to revoke + * + */ +int +db_revoke_object (DB_OBJECT_TYPE object_type, MOP user, MOP obj_, AU_TYPE auth) +{ + int retval = NO_ERROR; CHECK_CONNECT_ERROR (); - CHECK_2ARGS_ERROR (user, class_mop); + CHECK_2ARGS_ERROR (user, obj_); CHECK_MODIFICATION_ERROR (); - retval = do_check_partitioned_class (class_mop, CHECK_PARTITION_SUBS, NULL); + if (object_type == DB_OBJECT_CLASS) + { + retval = do_check_partitioned_class (obj_, CHECK_PARTITION_SUBS, NULL); + } + if (!retval) { - retval = au_revoke (user, class_mop, auth); + retval = au_revoke (object_type, user, obj_, auth, NULL); } return (retval); diff --git a/src/compat/db_method_static.cpp b/src/compat/db_method_static.cpp index 60970f4fc58..40a6590a92f 100644 --- a/src/compat/db_method_static.cpp +++ b/src/compat/db_method_static.cpp @@ -20,6 +20,8 @@ * db_method_static.cpp: implement static method links and their implementation */ +#include "msgcat_glossary.hpp" + #include "dbi.h" /* db_ */ #include "dbtype.h" #include "dbtype_def.h" @@ -357,7 +359,7 @@ au_add_member_method (MOP user, DB_VALUE *returnval, DB_VALUE *memval) else { error = ER_AU_NOT_OWNER; - er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_CLASS)); } } else @@ -424,7 +426,7 @@ au_drop_member_method (MOP user, DB_VALUE *returnval, DB_VALUE *memval) else { error = ER_AU_NOT_OWNER; - er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_CLASS)); } } else @@ -976,7 +978,7 @@ au_change_sp_owner_method (MOP obj, DB_VALUE *returnval, DB_VALUE *sp, DB_VALUE { if (owner != NULL && DB_IS_STRING (owner) && !DB_IS_NULL (owner) && db_get_string (owner) != NULL) { - sp_mop = jsp_find_stored_procedure (db_get_string (sp)); + sp_mop = jsp_find_stored_procedure (db_get_string (sp), DB_AUTH_NONE); if (sp_mop != NULL) { user = au_find_user (db_get_string (owner)); diff --git a/src/compat/db_obj.c b/src/compat/db_obj.c index e961293fa96..5c48bf0e34a 100644 --- a/src/compat/db_obj.c +++ b/src/compat/db_obj.c @@ -52,6 +52,7 @@ #include "schema_system_catalog_constants.h" #include "dbtype.h" #include "printer.hpp" +#include "jsp_cl.h" /* * OBJECT CREATION/DELETION @@ -1913,3 +1914,26 @@ db_get_serial_next_value_ex (const char *serial_name, DB_VALUE * serial_value, i return result; } + +/* + * db_find_procedure() - This function locates a procedure (function) with the given name. + * NULL is returned if a procedure by this name does not exist, or it the + * user does not have the appropriate access privilege for the procedure. + * If NULL is returned, the system sets the global error status to a value + * that indicates the exact nature of the error. + * return : procedure object (NULL if error) + * name(in): procedure name + */ + +DB_OBJECT * +db_find_procedure (const char *name) +{ + DB_OBJECT *retval; + + CHECK_CONNECT_NULL (); + CHECK_1ARG_NULL (name); + + retval = jsp_find_stored_procedure (name, DB_AUTH_NONE); + + return retval; +} diff --git a/src/compat/dbi.h b/src/compat/dbi.h index fc5e82be8fd..74f2b077c5b 100644 --- a/src/compat/dbi.h +++ b/src/compat/dbi.h @@ -153,6 +153,9 @@ extern "C" extern int db_set_user_comment (DB_OBJECT * user, const char *comment); extern int db_grant (DB_OBJECT * user, DB_OBJECT * classobj, DB_AUTH auth, int grant_option); extern int db_revoke (DB_OBJECT * user, DB_OBJECT * classobj, DB_AUTH auth); + extern int db_grant_object (DB_OBJECT_TYPE obj_type, DB_OBJECT * user, DB_OBJECT * obj_, DB_AUTH auth, + int grant_option); + extern int db_revoke_object (DB_OBJECT_TYPE obj_type, DB_OBJECT * user, DB_OBJECT * obj_, DB_AUTH auth); extern int db_check_authorization (DB_OBJECT * op, DB_AUTH auth); extern int db_check_authorization_and_grant_option (MOP op, DB_AUTH auth); extern int db_get_class_privilege (DB_OBJECT * op, unsigned int *auth); @@ -416,6 +419,9 @@ extern "C" extern int db_trigger_action (DB_OBJECT * trobj, char **action); extern int db_trigger_comment (DB_OBJECT * trobj, char **comment); +/* Procedure functions */ + extern DB_OBJECT *db_find_procedure (const char *name); + /* Schema template functions */ extern DB_CTMPL *dbt_create_class (const char *name); extern DB_CTMPL *dbt_create_vclass (const char *name); @@ -742,6 +748,8 @@ extern "C" extern void db_clear_host_connected (void); extern char *db_get_database_version (void); + + extern DB_OBJECT_TYPE db_get_object_type (DB_OBJECT * obj_); #ifdef __cplusplus } #endif diff --git a/src/compat/dbi_compat.h b/src/compat/dbi_compat.h index b3a1d921cde..ce13ff58e96 100644 --- a/src/compat/dbi_compat.h +++ b/src/compat/dbi_compat.h @@ -212,8 +212,11 @@ extern "C" extern int db_drop_member (DB_OBJECT * user, DB_OBJECT * member); extern int db_set_password (DB_OBJECT * user, const char *oldpass, const char *newpass); extern int db_set_user_comment (DB_OBJECT * user, const char *comment); - extern int db_grant (DB_OBJECT * user, DB_OBJECT * classobj, DB_AUTH auth, int grant_option); - extern int db_revoke (DB_OBJECT * user, DB_OBJECT * classobj, DB_AUTH auth); + extern int db_grant (DB_OBJECT * user, DB_OBJECT * obj_, DB_AUTH auth, int grant_option); + extern int db_revoke (DB_OBJECT * user, DB_OBJECT * obj_, DB_AUTH auth); + extern int db_grant_object (DB_OBJECT_TYPE obj_type, DB_OBJECT * user, DB_OBJECT * obj_, DB_AUTH auth, + int grant_option); + extern int db_revoke_object (DB_OBJECT_TYPE obj_type, DB_OBJECT * user, DB_OBJECT * obj_, DB_AUTH auth); extern int db_check_authorization (DB_OBJECT * op, DB_AUTH auth); extern int db_check_authorization_and_grant_option (MOP op, DB_AUTH auth); extern int db_get_class_privilege (DB_OBJECT * op, unsigned int *auth); @@ -453,6 +456,9 @@ extern "C" extern int db_trigger_action (DB_OBJECT * trobj, char **action); extern int db_trigger_comment (DB_OBJECT * trobj, char **comment); +/* Procedure functions */ + extern DB_OBJECT *db_find_procedure (const char *name); + /* Schema template functions */ extern DB_CTMPL *dbt_create_class (const char *name); extern DB_CTMPL *dbt_create_vclass (const char *name); diff --git a/src/compat/dbtype_def.h b/src/compat/dbtype_def.h index a1e71ccd864..a20c719f1fd 100644 --- a/src/compat/dbtype_def.h +++ b/src/compat/dbtype_def.h @@ -484,6 +484,17 @@ extern "C" DB_INSTANCE_OF_A_VCLASS_OF_A_CLASS = 'c', DB_INSTANCE_OF_A_VCLASS_OF_A_PROXY = 'd', DB_INSTANCE_OF_NONUPDATABLE_OBJECT = 'e' + } DB_INSTANCE_TYPE; + + typedef enum + { + DB_OBJECT_UNKNOWN = -1, + DB_OBJECT_CLASS = 0, /* TABLE, VIEW (_db_class) */ + DB_OBJECT_TRIGGER = 1, /* TRIGGER (_db_trigger) */ + DB_OBJECT_SERIAL = 2, /* SERIAL (db_serial) */ + DB_OBJECT_SERVER = 3, /* SERVER (db_server) */ + DB_OBJECT_SYNONYM = 4, /* SYNONYM (_db_synonym) */ + DB_OBJECT_PROCEDURE = 5 /* PROCEDURE, FUNCTION (_db_stored_procedure) */ } DB_OBJECT_TYPE; /* session state id */ @@ -537,11 +548,10 @@ extern "C" /* The lower limit for a number that can be represented by a numeric type */ #define DB_NUMERIC_UNDERFLOW_LIMIT 1e-38 -/* - * Change the maximum length of CHAR type to 2048 for memory allocation and performance. - * Refer to CBRD-25713 +/* The maximum precision of CHAR(n) domain that can be specified for an INTL_UTF8_MAX_CHAR_SIZE. + * We may need to define this functionally as the maximum precision will depend on the size multiplier of the codeset. */ -#define DB_MAX_CHAR_PRECISION 2048 +#define DB_MAX_CHAR_PRECISION (DB_MAX_STRING_LENGTH/4) /* The maximum precision that can be specified for a CHARACTER VARYING domain.*/ #define DB_MAX_VARCHAR_PRECISION DB_MAX_STRING_LENGTH diff --git a/src/connection/connection_defs.h b/src/connection/connection_defs.h index fb36d7f9003..994196c70cf 100644 --- a/src/connection/connection_defs.h +++ b/src/connection/connection_defs.h @@ -107,7 +107,6 @@ enum css_client_request CANCEL_SHUTDOWN = 15, GET_SHUTDOWN_TIME = 16, KILL_SERVER_IMMEDIATE = 17, - SHUTDOWN_REVIVING_SERVER = 18, GET_REPL_LIST = 20, /* REPL: get the info. for a process */ GET_ALL_LIST = 21, /* REPL: get the info. for all processes */ GET_REPL_COUNT = 22, /* REPL: get the # of repl processes */ diff --git a/src/connection/connection_globals.h b/src/connection/connection_globals.h index 06973ebb487..20cb63c7618 100644 --- a/src/connection/connection_globals.h +++ b/src/connection/connection_globals.h @@ -32,8 +32,6 @@ #define CSS_MAX_CLIENT_COUNT 4000 -#define CSS_SERVER_PROC_REGISTER_INITIALIZER {-1, "", 0, "", ""} - typedef bool (*CSS_CHECK_CLIENT_TYPE) (BOOT_CLIENT_TYPE client_type); typedef int (*CSS_GET_MAX_CONN_NUM) (void); @@ -59,26 +57,6 @@ typedef struct css_conn_rule_info int num_curr_conn; } CSS_CONN_RULE_INFO; -/* - * server register resource message body - */ - -/* process register */ -typedef struct css_server_proc_register CSS_SERVER_PROC_REGISTER; -struct css_server_proc_register -{ - static constexpr int CSS_SERVER_MAX_SZ_SERVER_NAME = 256; - static constexpr int CSS_SERVER_MAX_SZ_PROC_EXEC_PATH = 128; - static constexpr int CSS_SERVER_MAX_SZ_PROC_ARGS = 1024; - - int pid; - char server_name[CSS_SERVER_MAX_SZ_SERVER_NAME]; - int server_name_length; - - char exec_path[CSS_SERVER_MAX_SZ_PROC_EXEC_PATH]; - char args[CSS_SERVER_MAX_SZ_PROC_ARGS]; -}; - extern int css_Service_id; extern const char *css_Service_name; diff --git a/src/connection/connection_sr.c b/src/connection/connection_sr.c index d76848d12f8..260a07670f9 100644 --- a/src/connection/connection_sr.c +++ b/src/connection/connection_sr.c @@ -151,9 +151,6 @@ CSS_THREAD_FN css_Request_handler = NULL; /* This will handle closed connection errors */ CSS_THREAD_FN css_Connection_error_handler = NULL; -static char css_Server_exec_path[PATH_MAX]; -static char **css_Server_argv; - #define CSS_CONN_IDX(conn_arg) ((conn_arg) - css_Conn_array) #define CSS_FREE_CONN_MSG "Free count = %d, head = %d" @@ -1076,32 +1073,6 @@ css_common_connect (CSS_CONN_ENTRY * conn, unsigned short *rid, return NULL; } -/* - * css_set_proc_register() - make a server proc register. - * return: - * server_name(in): - * server_name_lenth(in): - * proc_register(out): - */ -static void -css_set_proc_register (const char *server_name, int server_name_length, CSS_SERVER_PROC_REGISTER * proc_register) -{ - char *p, *last; - char **argv; - - memcpy (proc_register->server_name, server_name, server_name_length); - proc_register->server_name_length = server_name_length; - proc_register->pid = getpid (); - strncpy_bufsize (proc_register->exec_path, css_Server_exec_path); - - p = (char *) proc_register->args; - last = p + proc_register->CSS_SERVER_MAX_SZ_PROC_ARGS; - for (argv = css_Server_argv; *argv; argv++) - { - p += snprintf (p, MAX ((last - p), 0), "%s ", *argv); - } -} - /* * css_connect_to_master_server() - Connect to the master from the server. * return: connection entry if success, or NULL @@ -1122,9 +1093,6 @@ css_connect_to_master_server (int master_port_id, const char *server_name, int n std::string pname; int datagram_fd, socket_fd; #endif - const char *data; - int data_length; - CSS_SERVER_PROC_REGISTER proc_register = CSS_SERVER_PROC_REGISTER_INITIALIZER; css_Service_id = master_port_id; if (GETHOSTNAME (hname, CUB_MAXHOSTNAMELEN) != 0) @@ -1140,27 +1108,18 @@ css_connect_to_master_server (int master_port_id, const char *server_name, int n } /* select the connection protocol */ - - // TODO : When supporting the Windows environment, It will be modified to send the same data - // (proc_register) for the Windows protocol (SERVER_REQUEST_NEW) as well. - if (css_Server_use_new_connection_protocol) { // Windows connection_protocol = SERVER_REQUEST_NEW; - data = server_name; - data_length = name_length; } else { // Linux and Unix connection_protocol = SERVER_REQUEST; - css_set_proc_register (server_name, name_length, &proc_register); - data = (const char *) &proc_register; - data_length = sizeof (proc_register); } - if (css_common_connect (conn, &rid, hname, connection_protocol, data, data_length, master_port_id) == NULL) + if (css_common_connect (conn, &rid, hname, connection_protocol, server_name, name_length, master_port_id) == NULL) { goto fail_end; } @@ -3163,29 +3122,3 @@ css_free_user_access_status (void) return; } - -/* - * css_set_exec_path () - - * return: none - * - * exec_path(in): - */ -void -css_set_exec_path (char *exec_path) -{ - assert (exec_path != NULL); - strncpy (css_Server_exec_path, exec_path, sizeof (css_Server_exec_path) - 1); -} - -/* - * css_set_argv () - - * return: none - * - * argv(in): - */ -void -css_set_argv (char **argv) -{ - assert (argv != NULL); - css_Server_argv = argv; -} diff --git a/src/connection/connection_sr.h b/src/connection/connection_sr.h index b639786fdf5..f34f0960020 100644 --- a/src/connection/connection_sr.h +++ b/src/connection/connection_sr.h @@ -192,7 +192,4 @@ extern void css_set_user_access_status (const char *db_user, const char *host, c extern void css_get_user_access_status (int num_user, LAST_ACCESS_STATUS ** access_status_array); extern void css_free_user_access_status (void); -extern void css_set_exec_path (char *exec_path); -extern void css_set_argv (char **argv); - #endif /* _CONNECTION_SR_H_ */ diff --git a/src/connection/server_support.c b/src/connection/server_support.c index 0a61e368b75..3255f503f33 100644 --- a/src/connection/server_support.c +++ b/src/connection/server_support.c @@ -66,7 +66,7 @@ #include "log_manager.h" #include "network.h" #include "object_representation.h" -#include "jsp_sr.h" +#include "pl_sr.h" #include "show_scan.h" #if defined(WINDOWS) #include "wintcp.h" @@ -321,7 +321,7 @@ css_setup_server_loop (void) #endif /* not WINDOWS */ #if defined(SA_MODE) && (defined(LINUX) || defined(x86_SOLARIS) || defined(HPUX)) - if (!jsp_jvm_is_loaded ()) + if (!pl_jvm_is_loaded ()) { (void) os_set_signal_handler (SIGFPE, SIG_IGN); } diff --git a/src/executables/commdb.c b/src/executables/commdb.c index cfd1f99a81f..95860490dd4 100644 --- a/src/executables/commdb.c +++ b/src/executables/commdb.c @@ -135,8 +135,6 @@ static bool commdb_Arg_deact_confirm_no_server = false; static char *commdb_Arg_host_name = NULL; static bool commdb_Arg_ha_start_util_process = false; static char *commdb_Arg_ha_util_process_args = NULL; -static bool commdb_Arg_shutdown_reviving_server = false; -static char *commdb_Arg_shutdown_reviving_server_name = NULL; /* * send_request_no_args() - send request without argument @@ -1065,18 +1063,6 @@ process_ha_start_util_process (CSS_CONN_ENTRY * conn, char *args) return error; } -/* - * process_shutdown_reviving_server() - shutdown reviving server - * return: none - * server_name(in) : server name - * conn(in) : connection info - */ -static void -process_shutdown_reviving_server (CSS_CONN_ENTRY * conn, char *server_name) -{ - send_request_one_arg (conn, SHUTDOWN_REVIVING_SERVER, server_name, (int) strlen (server_name) + 1); -} - /* * process_batch_command() - process user command in batch mode * return: none @@ -1193,11 +1179,6 @@ process_batch_command (CSS_CONN_ENTRY * conn) return process_ha_start_util_process (conn, (char *) commdb_Arg_ha_util_process_args); } - if (commdb_Arg_shutdown_reviving_server) - { - process_shutdown_reviving_server (conn, (char *) commdb_Arg_shutdown_reviving_server_name); - } - return NO_ERROR; } @@ -1240,7 +1221,6 @@ main (int argc, char **argv) {COMMDB_HOST_L, 1, 0, COMMDB_HOST_S}, {COMMDB_HA_ADMIN_INFO_L, 0, 0, COMMDB_HA_ADMIN_INFO_S}, {COMMDB_HA_START_UTIL_PROCESS_L, 1, 0, COMMDB_HA_START_UTIL_PROCESS_S}, - {COMMDB_SHUTDOWN_REVIVING_SERVER_L, 1, 0, COMMDB_SHUTDOWN_REVIVING_SERVER_S}, {0, 0, 0, 0} }; @@ -1389,14 +1369,6 @@ main (int argc, char **argv) commdb_Arg_ha_util_process_args = strdup (optarg); commdb_Arg_ha_start_util_process = true; break; - case COMMDB_SHUTDOWN_REVIVING_SERVER_S: - if (commdb_Arg_shutdown_reviving_server_name != NULL) - { - free_and_init (commdb_Arg_shutdown_reviving_server_name); - } - commdb_Arg_shutdown_reviving_server_name = strdup (optarg); - commdb_Arg_shutdown_reviving_server = true; - break; default: util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT); goto usage; @@ -1467,10 +1439,6 @@ main (int argc, char **argv) { free_and_init (commdb_Arg_ha_util_process_args); } - if (commdb_Arg_shutdown_reviving_server_name != NULL) - { - free_and_init (commdb_Arg_shutdown_reviving_server_name); - } return status; } diff --git a/src/executables/compactdb.c b/src/executables/compactdb.c index decfb5187b2..79baa4a44d8 100644 --- a/src/executables/compactdb.c +++ b/src/executables/compactdb.c @@ -141,8 +141,6 @@ compactdb (UTIL_FUNCTION_ARG * arg) } } - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); if ((error = db_login ("DBA", NULL)) || (error = db_restart (arg->argv0, TRUE, database_name))) diff --git a/src/executables/compactdb_cl.c b/src/executables/compactdb_cl.c index 48561e4ac4d..44bf7c891bb 100644 --- a/src/executables/compactdb_cl.c +++ b/src/executables/compactdb_cl.c @@ -871,8 +871,6 @@ compactdb (UTIL_FUNCTION_ARG * arg) } } - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); if (standby_compactdb_flag) diff --git a/src/executables/csql.c b/src/executables/csql.c index 1c8777d41e3..e2be472c5eb 100644 --- a/src/executables/csql.c +++ b/src/executables/csql.c @@ -1539,11 +1539,11 @@ csql_set_server_output (CSQL_ARGUMENT * csql_arg, bool server_output) csql_arg->pl_server_output = server_output; if (server_output) { - csql_execute_query ("CALL enable (50000);"); + csql_execute_query ("CALL dbms_output.enable (50000);"); } else { - csql_execute_query ("CALL disable ();"); + csql_execute_query ("CALL dbms_output.disable ();"); } } @@ -1844,7 +1844,7 @@ csql_print_server_output (const CSQL_ARGUMENT * csql_arg) bool print_header = true; do { - errors = csql_execute_query ("CALL get_line (:pl_output_str, :pl_output_status);"); + errors = csql_execute_query ("CALL dbms_output.get_line (:pl_output_str, :pl_output_status);"); if (errors != 0) { break; diff --git a/src/executables/master.c b/src/executables/master.c index 030350db9a5..6249bce0a55 100644 --- a/src/executables/master.c +++ b/src/executables/master.c @@ -59,7 +59,6 @@ #include "error_manager.h" #include "connection_globals.h" #include "connection_cl.h" -#include "system_parameter.h" #if defined(WINDOWS) #include "wintcp.h" #else /* ! WINDOWS */ @@ -74,7 +73,6 @@ #include "message_catalog.h" #include "dbi.h" #include "util_func.h" -#include "master_server_monitor.hpp" static void css_master_error (const char *error_string); static int css_master_timeout (void); @@ -82,7 +80,8 @@ static int css_master_init (int cport, SOCKET * clientfd); static void css_reject_client_request (CSS_CONN_ENTRY * conn, unsigned short rid, int reason); static void css_reject_server_request (CSS_CONN_ENTRY * conn, int reason); static void css_accept_server_request (CSS_CONN_ENTRY * conn, int reason); -static void css_accept_new_request (CSS_CONN_ENTRY * conn, unsigned short rid, char *buffer); +static void css_accept_new_request (CSS_CONN_ENTRY * conn, unsigned short rid, char *server_name, + int server_name_length); static void css_accept_old_request (CSS_CONN_ENTRY * conn, unsigned short rid, SOCKET_QUEUE_ENTRY * entry, char *server_name, int server_name_length); static void css_register_new_server (CSS_CONN_ENTRY * conn, unsigned short rid); @@ -320,53 +319,39 @@ css_accept_server_request (CSS_CONN_ENTRY * conn, int reason) * return: none * conn(in) * rid(in) - * buffer(in) - * + * server_name(in) + * server_name_length(in) */ static void -css_accept_new_request (CSS_CONN_ENTRY * conn, unsigned short rid, char *buffer) +css_accept_new_request (CSS_CONN_ENTRY * conn, unsigned short rid, char *server_name, int server_name_length) { char *datagram; - char *server_name; int datagram_length; SOCKET server_fd = INVALID_SOCKET; int length; - int server_name_length; CSS_CONN_ENTRY *datagram_conn; SOCKET_QUEUE_ENTRY *entry; - CSS_SERVER_PROC_REGISTER *proc_register = (CSS_SERVER_PROC_REGISTER *) buffer; datagram = NULL; datagram_length = 0; - css_accept_server_request (conn, SERVER_REQUEST_ACCEPTED); - if (css_receive_data (conn, rid, &datagram, &datagram_length, -1) == NO_ERRORS) { - if (datagram != NULL && css_tcp_master_datagram (datagram, &server_fd)) { datagram_conn = css_make_conn (server_fd); #if defined(DEBUG) css_Active_server_count++; #endif - css_add_request_to_socket_queue (datagram_conn, false, proc_register->server_name, server_fd, READ_WRITE, 0, + css_add_request_to_socket_queue (datagram_conn, false, server_name, server_fd, READ_WRITE, 0, &css_Master_socket_anchor); - - // Note : server_name is usually packed(appended) information of server_name, version_string, env_var, pid, - // packed from css_pack_server_name(). Since there are some cases that returns server_name and server_name_length - // as NULL, we need to check if server_name is packed information or not. - length = (int) strlen (proc_register->server_name) + 1; - server_name_length = proc_register->server_name_length; - - assert (length <= DB_MAX_IDENTIFIER_LENGTH); - + length = (int) strlen (server_name) + 1; if (length < server_name_length) { - entry = css_return_entry_of_server (proc_register->server_name, css_Master_socket_anchor); + entry = css_return_entry_of_server (server_name, css_Master_socket_anchor); if (entry != NULL) { - server_name = proc_register->server_name + length; + server_name += length; entry->version_string = (char *) malloc (strlen (server_name) + 1); if (entry->version_string != NULL) { @@ -389,19 +374,6 @@ css_accept_new_request (CSS_CONN_ENTRY * conn, unsigned short rid, char *buffer) } } } - - if (!entry->ha_mode) - { -#if !defined(WINDOWS) - if (auto_Restart_server) - { - /* *INDENT-OFF* */ - master_Server_monitor->produce_job (server_monitor::job_type::REGISTER_SERVER, proc_register->pid, - proc_register->exec_path, proc_register->args, proc_register->server_name); - /* *INDENT-ON* */ - } -#endif - } } } if (datagram) @@ -468,26 +440,20 @@ css_accept_old_request (CSS_CONN_ENTRY * conn, unsigned short rid, SOCKET_QUEUE_ static void css_register_new_server (CSS_CONN_ENTRY * conn, unsigned short rid) { - int data_length; - char *data = NULL; + int name_length; + char *server_name = NULL; SOCKET_QUEUE_ENTRY *entry; - // Note: css_register_new_server() is used in two situations: - // 1. When a client requests to connect a cub_server to cub_master, which is already registered. - // 2. When a new cub_server requests to register itself to cub_master. - // For the first situation, css_register_new_server() receives the server name as data. - // For the second situation, css_register_new_server() receives CSS_SERVER_PROC_REGISTER as data. - // css_register_new_server determines which case it is by checking if the entry is NULL or not. - - if (css_receive_data (conn, rid, &data, &data_length, -1) == NO_ERRORS) + /* read server name */ + if (css_receive_data (conn, rid, &server_name, &name_length, -1) == NO_ERRORS) { - entry = css_return_entry_of_server (data, css_Master_socket_anchor); + entry = css_return_entry_of_server (server_name, css_Master_socket_anchor); if (entry != NULL) { if (IS_INVALID_SOCKET (entry->fd)) { /* accept a server that was auto-started */ - css_accept_old_request (conn, rid, entry, data, data_length); + css_accept_old_request (conn, rid, entry, server_name, name_length); } else { @@ -502,17 +468,18 @@ css_register_new_server (CSS_CONN_ENTRY * conn, unsigned short rid) #if defined(DEBUG) css_Active_server_count++; #endif - css_add_request_to_socket_queue (conn, false, data, conn->fd, READ_WRITE, 0, &css_Master_socket_anchor); + css_add_request_to_socket_queue (conn, false, server_name, conn->fd, READ_WRITE, 0, + &css_Master_socket_anchor); #else /* ! WINDOWS */ /* accept a request from a new server */ - css_accept_new_request (conn, rid, data); + css_accept_new_request (conn, rid, server_name, name_length); #endif /* ! WINDOWS */ } } - if (data != NULL) + if (server_name != NULL) { - free_and_init (data); + free_and_init (server_name); } #if !defined(WINDOWS) @@ -1013,15 +980,6 @@ css_check_master_socket_input (int *count, fd_set * fd_var) css_Active_server_count--; } #endif - -#if !defined(WINDOWS) - if (auto_Restart_server) - { - /* *INDENT-OFF* */ - master_Server_monitor->produce_job (server_monitor::job_type::REVIVE_SERVER, -1, "", "", temp->name); - /* *INDENT-ON* */ - } -#endif css_remove_entry_by_conn (temp->conn_ptr, &css_Master_socket_anchor); } } @@ -1263,18 +1221,6 @@ main (int argc, char **argv) goto cleanup; } } - - auto_Restart_server = prm_get_bool_value (PRM_ID_AUTO_RESTART_SERVER); - - // Since master_Server_monitor is a module for restarting abnormally terminated cub_server, - // it is initialized only when the 'auto_restart_server' parameter is set to true. - - if (auto_Restart_server) - { - // *INDENT-OFF* - master_Server_monitor.reset (new server_monitor ()); - // *INDENT-ON* - } #endif conn = css_make_conn (css_Master_socket_fd[0]); diff --git a/src/executables/master_request.c b/src/executables/master_request.c index 683e05952f9..20ae2620516 100644 --- a/src/executables/master_request.c +++ b/src/executables/master_request.c @@ -56,7 +56,6 @@ #include "master_util.h" #include "master_request.h" #include "master_heartbeat.h" -#include "master_server_monitor.hpp" #if defined (SUPPRESS_STRLEN_WARNING) #define strlen(s1) ((int) strlen(s1)) @@ -531,14 +530,6 @@ css_process_kill_slave (CSS_CONN_ENTRY * conn, unsigned short request_id, char * snprintf (buffer, MASTER_TO_SRV_MSG_SIZE, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MASTER, MASTER_MSG_SERVER_STATUS), server_name, timeout); -#if !defined(WINDOWS) - if (auto_Restart_server) - { - /* *INDENT-OFF* */ - master_Server_monitor->produce_job (server_monitor::job_type::UNREGISTER_SERVER, -1, "", "", server_name); - /* *INDENT-ON* */ - } -#endif css_process_start_shutdown (temp, timeout * 60, buffer); } snprintf (buffer, MASTER_TO_SRV_MSG_SIZE, @@ -606,54 +597,6 @@ css_process_kill_immediate (CSS_CONN_ENTRY * conn, unsigned short request_id, ch } } -/* - * css_process_start_shutdown_by_name() - * return: none - * server_name(in/out) - */ -void -css_process_start_shutdown_by_name (char *server_name) -{ -#if !defined(WINDOWS) - SOCKET_QUEUE_ENTRY *temp; - char buffer[MASTER_TO_SRV_MSG_SIZE]; - - (void) pthread_mutex_lock (&css_Master_socket_anchor_lock); - - for (temp = css_Master_socket_anchor; temp; temp = temp->next) - { - if ((temp->name != NULL) && (strcmp (temp->name, server_name) == 0)) - { - /* Send a shutdown request to the specified cub_server with a timeout of 0. - * Buffer will be unused in the receiving function (css_process_shutdown_request). */ - css_process_start_shutdown (temp, 0, buffer); - } - } - (void) pthread_mutex_unlock (&css_Master_socket_anchor_lock); -#endif -} - - -/* - * css_process_shutdown_reviving_server() - * return: none - * conn(in) - * request_id(in) - * server_name(in/out) - */ -static void -css_process_shutdown_reviving_server (CSS_CONN_ENTRY * conn, unsigned short request_id, char *server_name) -{ -#if !defined(WINDOWS) - if (auto_Restart_server) - { - /* *INDENT-OFF* */ - master_Server_monitor->produce_job (server_monitor::job_type::SHUTDOWN_SERVER, -1, "", "", server_name); - /* *INDENT-ON* */ - } -#endif -} - /* * css_send_term_signal() - send a signal to the target process * return: none @@ -766,14 +709,6 @@ css_process_shutdown (char *time_buffer) memset (buffer, 0, sizeof (buffer)); snprintf (buffer, MASTER_TO_SRV_MSG_SIZE, msgcat_message (MSGCAT_CATALOG_UTILS, MSGCAT_UTIL_SET_MASTER, MASTER_MSG_GOING_DOWN), timeout); -#if !defined(WINDOWS) - if (auto_Restart_server) - { - /* INDENT-OFF */ - master_Server_monitor.reset (); - /* INDENT-ON */ - } -#endif for (temp = css_Master_socket_anchor; temp; temp = temp->next) { @@ -1986,12 +1921,6 @@ css_process_info_request (CSS_CONN_ENTRY * conn) css_process_kill_immediate (conn, request_id, buffer); } break; - case SHUTDOWN_REVIVING_SERVER: - if (buffer != NULL) - { - css_process_shutdown_reviving_server (conn, request_id, buffer); - } - break; case GET_ALL_COUNT: css_process_all_count_info (conn, request_id); break; diff --git a/src/executables/master_request.h b/src/executables/master_request.h index 2141b8d6080..f55fc605c03 100644 --- a/src/executables/master_request.h +++ b/src/executables/master_request.h @@ -57,5 +57,4 @@ extern SOCKET_QUEUE_ENTRY *css_add_request_to_socket_queue (CSS_CONN_ENTRY * con SOCKET fd, int fd_type, int pid, SOCKET_QUEUE_ENTRY ** anchor_p); extern SOCKET_QUEUE_ENTRY *css_return_entry_by_conn (CSS_CONN_ENTRY * conn_p, SOCKET_QUEUE_ENTRY ** anchor_p); -extern void css_process_start_shutdown_by_name (char *server_name); #endif /* _MASTER_REQUEST_H_ */ diff --git a/src/executables/master_server_monitor.cpp b/src/executables/master_server_monitor.cpp deleted file mode 100644 index 92da0ee0cf4..00000000000 --- a/src/executables/master_server_monitor.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// -// master_server_monitor.cpp - Server Revive monitoring module -// - -#include -#include -#include -#include - -#include "master_server_monitor.hpp" - -std::unique_ptr master_Server_monitor = nullptr; -bool auto_Restart_server = false; - -server_monitor::server_monitor () -{ - - m_server_entry_map = std::unordered_map (); - - { - std::lock_guard lock (m_server_monitor_mutex); - m_thread_shutdown = false; - } - - start_monitoring_thread (); - _er_log_debug (ARG_FILE_LINE, "[Server Monitor] Monitoring started."); -} - -// In server_monitor destructor, it should guarentee that -// m_monitoring_thread is terminated before m_monitor_list is deleted. -server_monitor::~server_monitor () -{ - stop_monitoring_thread (); - _er_log_debug (ARG_FILE_LINE, "[Server Monitor] Monitoring finished."); -} - -void -server_monitor::start_monitoring_thread () -{ - m_monitoring_thread = std::make_unique (&server_monitor::server_monitor_thread_worker, this); -} - -void -server_monitor::stop_monitoring_thread () -{ - { - std::lock_guard lock (m_server_monitor_mutex); - m_thread_shutdown = true; - } - m_monitor_cv_consumer.notify_all(); - - m_monitoring_thread->join(); -} - -void -server_monitor::server_monitor_thread_worker () -{ - job job; - - while (true) - { - { - std::unique_lock lock (m_server_monitor_mutex); - - m_monitor_cv_consumer.wait (lock, [this] - { - return !m_job_queue.empty () || m_thread_shutdown; - }); - - if (m_thread_shutdown) - { - break; - } - else - { - assert (!m_job_queue.empty ()); - consume_job (job); - } - } - process_job (job); - } -} - -void -server_monitor::register_server_entry (int pid, const std::string &exec_path, const std::string &args, - const std::string &server_name - ) -{ - auto entry = m_server_entry_map.find (server_name); - - if (entry != m_server_entry_map.end ()) - { - entry->second.set_pid (pid); - entry->second.set_need_revive (false); - entry->second.set_last_revived_time (std::chrono::steady_clock::now ()); - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Server entry has been registered. (pid : %d)", - server_name.c_str(), pid); - } - else - { - m_server_entry_map.emplace (std::move (server_name), server_entry (pid, exec_path, args, - std::chrono::steady_clock::time_point ())); - - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Server entry has been registered newly. (pid : %d)", - server_name.c_str(), pid); - } -} - -void -server_monitor::remove_server_entry (const std::string &server_name) -{ - auto entry = m_server_entry_map.find (server_name); - assert (entry != m_server_entry_map.end ()); - - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Server entry has been unregistered. (pid : %d)", - server_name.c_str(), entry->second.get_pid()); - - m_server_entry_map.erase (entry); -} - -void -server_monitor::revive_server (const std::string &server_name) -{ - int error_code; - - // Unacceptable revive time difference is set to be 120 seconds - // as the timediff of server restart mechanism of heartbeat. - constexpr int SERVER_MONITOR_UNACCEPTABLE_REVIVE_TIMEDIFF_IN_SECS = 120; - std::chrono::steady_clock::time_point tv; - int out_pid; - - auto entry = m_server_entry_map.find (server_name); - - if (entry != m_server_entry_map.end ()) - { - entry->second.set_need_revive (true); - - tv = std::chrono::steady_clock::now (); - auto timediff = std::chrono::duration_cast (tv - - entry->second.get_last_revived_time()).count(); - bool revived_before = entry->second.get_last_revived_time () != std::chrono::steady_clock::time_point (); - - // If the server is abnormally terminated and revived within a short period of time, it is considered as a repeated failure. - // For HA server, heartbeat handle this case as demoting the server from master to slave and keep trying to revive the server. - // However, in this case, the server_monitor will not try to revive the server due to following reasons. - // 1. preventing repeated creation of core files. - // 2. The service cannot be recovered even if revived if the server abnormally terminates again within a short time. - - // TODO: Consider retry count for repeated failure case, and give up reviving the server after several retries. - // TODO: The timediff value continues to increase if REVIVE_SERVER handling is repeated. Thus, the if condition will always be - // true after the first evaluation. Therefore, evaluating the timediff only once when producing the REVIVE_SERVER job is needed. - // (Currently, it is impossible since last_revived_time is stored in server_entry, which is not synchronized structure between monitor and main thread.) - - if (!revived_before || timediff > SERVER_MONITOR_UNACCEPTABLE_REVIVE_TIMEDIFF_IN_SECS) - { - out_pid = try_revive_server (entry->second.get_exec_path(), entry->second.get_argv()); - if (out_pid == -1) - { - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Failed to fork server process. Server monitor try to revive server again.", - entry->first.c_str()); - produce_job_internal (job_type::REVIVE_SERVER, -1, "", "", entry->first); - } - else - { - entry->second.set_pid (out_pid); - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Server monitor is waiting for server to be registered. (pid : %d)", - entry->first.c_str(), entry->second.get_pid()); - produce_job_internal (job_type::CONFIRM_REVIVE_SERVER, -1, "", "", - entry->first); - } - return; - } - else - { - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Server process failures occurred again within a short period of time(%d sec). It will no longer be revived automatically. (pid : %d)", - entry->first.c_str(), SERVER_MONITOR_UNACCEPTABLE_REVIVE_TIMEDIFF_IN_SECS, entry->second.get_pid()); - m_server_entry_map.erase (entry); - return; - } - } -} - -void -server_monitor::check_server_revived (const std::string &server_name) -{ - int error_code; - auto entry = m_server_entry_map.find (server_name); - - if (entry != m_server_entry_map.end ()) - { - error_code = kill (entry->second.get_pid (), 0); - if (error_code) - { - if (errno == ESRCH) - { - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Revived server process can not be found. Server monitor will try to revive server again. (pid : %d)", - entry->first.c_str(), entry->second.get_pid()); - produce_job_internal (job_type::REVIVE_SERVER, -1, "", "", entry->first); - } - else - { - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Failed to revive server due to unknown error from kill() function. It will no longer be revived automatically. (pid : %d)", - entry->first.c_str(), entry->second.get_pid()); - kill (entry->second.get_pid (), SIGKILL); - m_server_entry_map.erase (entry); - } - } - else if (entry->second.get_need_revive ()) - { - // Server revive confirm interval is set to be 1 second to avoid busy waiting. - constexpr int SERVER_MONITOR_CONFIRM_REVIVE_INTERVAL_IN_SECS = 1; - - std::this_thread::sleep_for (std::chrono::seconds (SERVER_MONITOR_CONFIRM_REVIVE_INTERVAL_IN_SECS)); - - produce_job_internal (job_type::CONFIRM_REVIVE_SERVER, -1, "", "", - entry->first); - - } - else - { - _er_log_debug (ARG_FILE_LINE, "[Server Monitor] [%s] Server revive success. (pid : %d)", - entry->first.c_str(), - entry->second.get_pid()); - } - return; - } -} - -int -server_monitor::try_revive_server (const std::string &exec_path, char *const *argv) -{ - pid_t pid; - - pid = fork (); - if (pid < 0) - { - return -1; - } - else if (pid == 0) - { - execv (exec_path.c_str(), argv); - } - else - { - return pid; - } -} -void -server_monitor::shutdown_server (const std::string &server_name) -{ - int rv; - auto entry = m_server_entry_map.find (server_name); - - if (entry != m_server_entry_map.end ()) - { - - if (entry->second.get_need_revive ()) - { - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Server is shutdown. Reviving the server will not be tried.", - server_name.c_str()); - } - else - { - css_process_start_shutdown_by_name (const_cast (server_name.c_str())); - - _er_log_debug (ARG_FILE_LINE, - "[Server Monitor] [%s] Server is already revived. Server monitor will terminate the server. (pid : %d)", - server_name.c_str(), entry->second.get_pid()); - } - m_server_entry_map.erase (entry); - } -} - -void -server_monitor::produce_job_internal (job_type job_type, int pid, const std::string &exec_path, - const std::string &args, const std::string &server_name) -{ - std::lock_guard lock (m_server_monitor_mutex); - m_job_queue.emplace (job_type, pid, exec_path, args, server_name); -} - -void -server_monitor::produce_job (job_type job_type, int pid, const std::string &exec_path, - const std::string &args, const std::string &server_name) -{ - produce_job_internal (job_type, pid, exec_path, args, server_name); - m_monitor_cv_consumer.notify_all(); -} - -void -server_monitor::consume_job (job &consume_job) -{ - consume_job = std::move (m_job_queue.front ()); - m_job_queue.pop (); -} - -void -server_monitor::process_job (job &consume_job) -{ - switch (consume_job.get_job_type ()) - { - case job_type::REGISTER_SERVER: - register_server_entry (consume_job.get_pid(), consume_job.get_exec_path(), consume_job.get_args(), - consume_job.get_server_name()); - - break; - case job_type::UNREGISTER_SERVER: - remove_server_entry (consume_job.get_server_name()); - break; - case job_type::REVIVE_SERVER: - revive_server (consume_job.get_server_name()); - break; - case job_type::CONFIRM_REVIVE_SERVER: - check_server_revived (consume_job.get_server_name()); - break; - case job_type::SHUTDOWN_SERVER: - shutdown_server (consume_job.get_server_name()); - break; - case job_type::JOB_MAX: - default: - assert (false); - break; - } -} - -server_monitor::job:: -job (job_type job_type, int pid, const std::string &exec_path, const std::string &args, - const std::string &server_name) - : m_job_type {job_type} - , m_pid {pid} - , m_exec_path {exec_path} - , m_args {args} - , m_server_name {server_name} -{ -} - -server_monitor::job_type -server_monitor::job::get_job_type () const -{ - return m_job_type; -} - -int -server_monitor::job::get_pid () const -{ - return m_pid; -} - -std::string -server_monitor::job::get_exec_path () const -{ - return m_exec_path; -} - -std::string -server_monitor::job::get_args () const -{ - return m_args; -} - -std::string -server_monitor::job::get_server_name () const -{ - return m_server_name; -} - -server_monitor::server_entry:: -server_entry (int pid, const std::string &exec_path, const std::string &args, - std::chrono::steady_clock::time_point revive_time) - : m_pid {pid} - , m_exec_path {exec_path} - , m_need_revive {false} - , m_last_revived_time {revive_time} -{ - if (args.size() > 0) - { - proc_make_arg (args); - } -} - -int -server_monitor::server_entry::get_pid () const -{ - return m_pid; -} - -std::string -server_monitor::server_entry::get_exec_path () const -{ - return m_exec_path; -} - -char *const * -server_monitor::server_entry::get_argv () const -{ - return m_argv.get (); -} - -bool -server_monitor::server_entry::get_need_revive () const -{ - return m_need_revive; -} - -std::chrono::steady_clock::time_point -server_monitor::server_entry::get_last_revived_time () const -{ - return m_last_revived_time; -} - -void -server_monitor::server_entry::set_pid (int pid) -{ - m_pid = pid; -} - -void -server_monitor::server_entry::set_exec_path (const std::string &exec_path) -{ - m_exec_path = exec_path; -} - -void -server_monitor::server_entry::set_need_revive (bool need_revive) -{ - m_need_revive = need_revive; -} - -void -server_monitor::server_entry::set_last_revived_time (std::chrono::steady_clock::time_point revive_time) -{ - m_last_revived_time = revive_time; -} - -void -server_monitor::server_entry::proc_make_arg (const std::string &args) -{ - //argv is type of std::unique_ptr - m_argv = std::make_unique (args.size () + 1); - std::istringstream iss (args); - std::string arg; - int i = 0; - while (std::getline (iss, arg, ' ')) - { - m_argv[i] = new char[arg.size () + 1]; - std::copy (arg.begin (), arg.end (), m_argv[i]); - i++; - } - m_argv[args.size()] = nullptr; -} diff --git a/src/executables/master_server_monitor.hpp b/src/executables/master_server_monitor.hpp deleted file mode 100644 index f8ca8dd3c2e..00000000000 --- a/src/executables/master_server_monitor.hpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * master_server_monitor.hpp - - */ - -#ifndef _MASTER_SERVER_MONITOR_HPP_ -#define _MASTER_SERVER_MONITOR_HPP_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "connection_globals.h" -#include "master_request.h" - -class server_monitor -{ - - public: - - enum class job_type - { - REGISTER_SERVER = 0, - UNREGISTER_SERVER = 1, - REVIVE_SERVER = 2, - CONFIRM_REVIVE_SERVER = 3, - SHUTDOWN_SERVER = 4, - JOB_MAX - }; - - private: - - class job - { - - public: - - job (job_type job_type, int pid, const std::string &exec_path, const std::string &args, - const std::string &server_name); - job () : m_job_type (job_type::JOB_MAX) {}; - ~job () {}; - - job (const job &) = default; - job (job &&) = default; - - job &operator= (const job &) = delete; - job &operator= (job &&) = default; - - job_type get_job_type () const; - int get_pid () const; - std::string get_exec_path () const; - std::string get_args () const; - std::string get_server_name () const; - - private: - - job_type m_job_type; // job type - int m_pid; // process ID of server process - std::string m_exec_path; // executable path of server process - std::string m_args; // arguments of server process - std::string m_server_name; // server name - }; - - public: - - server_monitor (); - ~server_monitor (); - - server_monitor (const server_monitor &) = delete; - server_monitor (server_monitor &&) = delete; - - server_monitor &operator = (const server_monitor &) = delete; - server_monitor &operator = (server_monitor &&) = delete; - - void register_server_entry (int pid, const std::string &exec_path, const std::string &args, - const std::string &server_name); - void remove_server_entry (const std::string &server_name); - void revive_server (const std::string &server_name); - int try_revive_server (const std::string &exec_path, char *const *argv); - void check_server_revived (const std::string &server_name); - void shutdown_server (const std::string &server_name); - - void produce_job_internal (job_type job_type, int pid, const std::string &exec_path, const std::string &args, - const std::string &server_name); - void produce_job (job_type job_type, int pid, const std::string &exec_path, const std::string &args, - const std::string &server_name); - - void consume_job (job &consune_job); - void process_job (job &consume_job); - - private: - - class server_entry - { - public: - server_entry (int pid, const std::string &exec_path, const std::string &args, - std::chrono::steady_clock::time_point revive_time); - ~server_entry () {}; - - server_entry (const server_entry &) = delete; - server_entry (server_entry &&) = default; - - server_entry &operator= (const server_entry &) = delete; - server_entry &operator= (server_entry &&other) - { - if (this != &other) - { - m_pid = other.m_pid; - m_need_revive = other.m_need_revive; - m_last_revived_time = other.m_last_revived_time; - m_exec_path = other.m_exec_path; - m_argv = std::move (other.m_argv); - } - return *this; - } - - int get_pid () const; - std::string get_exec_path () const; - char *const *get_argv () const; - bool get_need_revive () const; - std::chrono::steady_clock::time_point get_last_revived_time () const; - - void set_pid (int pid); - void set_exec_path (const std::string &exec_path); - void set_need_revive (bool need_revive); - void set_last_revived_time (std::chrono::steady_clock::time_point revive_time); - - void proc_make_arg (const std::string &args); - - private: - int m_pid; // process ID of server process - std::string m_exec_path; // executable path of server process - std::unique_ptr m_argv; // arguments of server process - volatile bool m_need_revive; // need to be revived by monitoring thread - std::chrono::steady_clock::time_point m_last_revived_time; // last revived time - }; - - std::unordered_map m_server_entry_map; // map of server entries - std::unique_ptr m_monitoring_thread; // monitoring thread - std::queue m_job_queue; // job queue for monitoring thread - bool m_thread_shutdown; // flag to shutdown monitoring thread - std::mutex m_server_monitor_mutex; // lock that syncs m_job_queue and m_thread_shutdown - std::condition_variable m_monitor_cv_consumer; // condition variable for m_job_queue empty check - - void start_monitoring_thread (); - void stop_monitoring_thread (); - void server_monitor_thread_worker (); -}; - -extern std::unique_ptr master_Server_monitor; -extern bool auto_Restart_server; - -#endif diff --git a/src/executables/migrate.c b/src/executables/migrate.c index f0cee450c8c..9ebabcb5f68 100644 --- a/src/executables/migrate.c +++ b/src/executables/migrate.c @@ -468,7 +468,6 @@ main (int argc, char *argv[]) } sysprm_set_force (prm_get_name (PRM_ID_PB_NBUFFERS), "1024"); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); AU_DISABLE_PASSWORDS (); diff --git a/src/executables/javasp.cpp b/src/executables/pl.cpp similarity index 50% rename from src/executables/javasp.cpp rename to src/executables/pl.cpp index 45bff40e8df..4e58a0c9de6 100644 --- a/src/executables/javasp.cpp +++ b/src/executables/pl.cpp @@ -18,7 +18,7 @@ /* - * javasp.cpp - utility java stored procedure server main routine + * pl.cpp - utility PL JVM server main routine * */ @@ -54,6 +54,7 @@ #include #endif /* not WINDOWS */ +#include "process_util.h" #include "environment_variable.h" #include "system_parameter.h" #include "error_code.h" @@ -63,10 +64,10 @@ #include "databases_file.h" #include "object_representation.h" #include "method_struct_invoke.hpp" -#include "method_connection_java.hpp" - -#include "jsp_file.h" -#include "jsp_sr.h" +#include "pl_connection.hpp" +#include "pl_comm.h" +#include "pl_file.h" +#include "pl_sr.h" #include "packer.hpp" @@ -75,9 +76,9 @@ #include #include -#define JAVASP_PING_LEN PATH_MAX +#define PL_PING_LEN PATH_MAX -#define JAVASP_PRINT_ERR_MSG(...) \ +#define PL_PRINT_ERR_MSG(...) \ do {\ fprintf (stderr, __VA_ARGS__);\ }while (0) @@ -88,25 +89,22 @@ #define NULL_DEVICE "/dev/null" #endif -static int javasp_start_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_name, const std::string &path); -static int javasp_stop_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_name); -static int javasp_status_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_name); - -static void javasp_dump_status (FILE *fp, JAVASP_STATUS_INFO status_info); -static int javasp_ping_server (const int server_port, const char *db_name, char *buf); -static bool javasp_is_running (const int server_port, const std::string &db_name); +static int pl_start_server (const PL_SERVER_INFO pl_info, const std::string &db_name, const std::string &path); +static int pl_stop_server (const PL_SERVER_INFO pl_info, const std::string &db_name); +static int pl_status_server (const PL_SERVER_INFO pl_info, const std::string &db_name); -static bool javasp_is_terminated_process (int pid); -static void javasp_terminate_process (int pid); +static void pl_dump_status (FILE *fp, PL_STATUS_INFO status_info); +static int pl_ping_server (const PL_SERVER_INFO pl_info, const char *db_name, char *buf); +static bool pl_is_running (const PL_SERVER_INFO pl_info, const std::string &db_name); -static int javasp_get_server_info (const std::string &db_name, JAVASP_SERVER_INFO &info); -static int javasp_check_argument (int argc, char *argv[], std::string &command, std::string &db_name); -static int javasp_check_database (const std::string &db_name, std::string &db_path); +static int pl_get_server_info (const std::string &db_name, PL_SERVER_INFO &info); +static int pl_check_argument (int argc, char *argv[], std::string &command, std::string &db_name); +static int pl_check_database (const std::string &db_name, std::string &db_path); -static int javasp_get_port_param (); +static int pl_get_port_param (); #if !defined(WINDOWS) -static void javasp_signal_handler (int sig); +static void pl_signal_handler (int sig); #endif static bool is_signal_handling = false; @@ -114,7 +112,7 @@ static char executable_path[PATH_MAX]; static std::string command; static std::string db_name; -static JAVASP_SERVER_INFO running_info = JAVASP_SERVER_INFO_INITIALIZER; +static PL_SERVER_INFO running_info = PL_SERVER_INFO_INITIALIZER; /* * main() - javasp main function @@ -127,19 +125,19 @@ main (int argc, char *argv[]) FILE *redirect = NULL; /* for ping */ #if defined(WINDOWS) - FARPROC jsp_old_hook = NULL; + FARPROC pl_old_hook = NULL; #else if (os_set_signal_handler (SIGPIPE, SIG_IGN) == SIG_ERR) { return ER_GENERIC_ERROR; } - os_set_signal_handler (SIGABRT, javasp_signal_handler); - os_set_signal_handler (SIGILL, javasp_signal_handler); - os_set_signal_handler (SIGFPE, javasp_signal_handler); - os_set_signal_handler (SIGBUS, javasp_signal_handler); - os_set_signal_handler (SIGSEGV, javasp_signal_handler); - os_set_signal_handler (SIGSYS, javasp_signal_handler); + os_set_signal_handler (SIGABRT, pl_signal_handler); + os_set_signal_handler (SIGILL, pl_signal_handler); + os_set_signal_handler (SIGFPE, pl_signal_handler); + os_set_signal_handler (SIGBUS, pl_signal_handler); + os_set_signal_handler (SIGSEGV, pl_signal_handler); + os_set_signal_handler (SIGSYS, pl_signal_handler); #endif /* WINDOWS */ { @@ -151,7 +149,7 @@ main (int argc, char *argv[]) er_init (NULL_DEVICE, ER_NEVER_EXIT); /* check arguments, get command and database name */ - status = javasp_check_argument (argc, argv, command, db_name); + status = pl_check_argument (argc, argv, command, db_name); if (status != NO_ERROR) { return ER_GENERIC_ERROR; @@ -159,7 +157,7 @@ main (int argc, char *argv[]) /* check database exists and get path name of database */ std::string pathname; - status = javasp_check_database (db_name, pathname); + status = pl_check_database (db_name, pathname); if (status != NO_ERROR) { goto exit; @@ -177,13 +175,13 @@ main (int argc, char *argv[]) er_init (er_msg_file, ER_NEVER_EXIT); } - /* try to create info dir and get absolute path for info file; $CUBRID/var/javasp_.info */ - JAVASP_SERVER_INFO jsp_info = JAVASP_SERVER_INFO_INITIALIZER; - status = javasp_get_server_info (db_name, jsp_info); + /* try to create info dir and get absolute path for info file; $CUBRID/var/pl_.info */ + PL_SERVER_INFO pl_info = PL_SERVER_INFO_INITIALIZER; + status = pl_get_server_info (db_name, pl_info); if (status != NO_ERROR && command.compare ("start") != 0) { char info_path[PATH_MAX], err_msg[PATH_MAX + 32]; - javasp_get_info_file (info_path, PATH_MAX, db_name.c_str ()); + pl_get_info_file (info_path, PATH_MAX, db_name.c_str ()); snprintf (err_msg, sizeof (err_msg), "Error while opening file (%s)", info_path); er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_START_JVM, 1, err_msg); goto exit; @@ -191,7 +189,7 @@ main (int argc, char *argv[]) #if defined(WINDOWS) // socket startup for windows - windows_socket_startup (jsp_old_hook); + windows_socket_startup (pl_old_hook); #endif /* WINDOWS */ /* @@ -203,33 +201,34 @@ main (int argc, char *argv[]) if ((redirect = freopen (NULL_DEVICE, "w", stderr)) == NULL) { assert (false); - return ER_GENERIC_ERROR; + goto exit; } // check process is running - if (jsp_info.pid == JAVASP_PID_DISABLED || javasp_is_terminated_process (jsp_info.pid) == true) + if (pl_info.pid == PL_PID_DISABLED || is_terminated_process (pl_info.pid) == true) { - // NO_CONNECTION - javasp_reset_info (db_name.c_str ()); + fprintf (stdout, "NO_PROCESS"); goto exit; } - char buffer[JAVASP_PING_LEN] = {0}; + char buffer[PL_PING_LEN] = {0}; if (status == NO_ERROR) { - status = javasp_ping_server (jsp_info.port, db_name.c_str (), buffer); + status = pl_ping_server (pl_info, db_name.c_str (), buffer); } if (status == NO_ERROR) { std::string ping_db_name; - packing_unpacker unpacker (buffer, JAVASP_PING_LEN); + packing_unpacker unpacker (buffer, PL_PING_LEN); unpacker.unpack_string (ping_db_name); fprintf (stdout, "%s", ping_db_name.c_str ()); } else { + fprintf (stdout, "NO_CONNECTION"); + status = NO_ERROR; goto exit; } @@ -246,43 +245,51 @@ main (int argc, char *argv[]) /* javasp command main routine */ if (command.compare ("start") == 0) { - // check java stored procedure is not enabled - if (prm_get_bool_value (PRM_ID_JAVA_STORED_PROCEDURE) == false) - { - fprintf (stdout, "%s system parameter is not enabled\n", prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE)); - status = ER_SP_CANNOT_START_JVM; - goto exit; - } - - status = javasp_start_server (jsp_info, db_name, pathname); + status = pl_start_server (pl_info, db_name, pathname); if (status == NO_ERROR) { command = "running"; - javasp_read_info (db_name.c_str(), running_info); + pl_read_info (db_name.c_str(), running_info); do { - SLEEP_MILISEC (0, 100); +#if defined (WINDOWS) + DWORD parent_ppid = GetCurrentProcessId(); + HANDLE hParent = OpenProcess (SYNCHRONIZE, FALSE, parent_ppid); + DWORD result = WaitForSingleObject (hParent, INFINITE); + CloseHandle (hParent); + if (result == WAIT_OBJECT_0) + { + ExitProcess (0); + } +#else + if (getppid () == 1) + { + // parent process is terminated + break; + } +#endif + sleep (1); } while (true); } } else if (command.compare ("stop") == 0) { - status = javasp_stop_server (jsp_info, db_name); + status = pl_stop_server (pl_info, db_name); } else if (command.compare ("status") == 0) { - status = javasp_status_server (jsp_info, db_name); + status = pl_status_server (pl_info, db_name); } else { - JAVASP_PRINT_ERR_MSG ("Invalid command: %s\n", command.c_str ()); + PL_PRINT_ERR_MSG ("Invalid command: %s\n", command.c_str ()); status = ER_GENERIC_ERROR; } #if defined(WINDOWS) // socket shutdown for windows - windows_socket_shutdown (jsp_old_hook); + windows_socket_shutdown (pl_old_hook); #endif /* WINDOWS */ } @@ -294,10 +301,6 @@ main (int argc, char *argv[]) { fprintf (stdout, "ERROR"); } - else - { - fprintf (stdout, "NO_CONNECTION"); - } if (redirect) { @@ -308,7 +311,7 @@ main (int argc, char *argv[]) { if (er_has_error ()) { - JAVASP_PRINT_ERR_MSG ("%s\n", er_msg ()); + PL_PRINT_ERR_MSG ("%s\n", er_msg ()); } } @@ -316,9 +319,9 @@ main (int argc, char *argv[]) } #if !defined(WINDOWS) -static void javasp_signal_handler (int sig) +static void pl_signal_handler (int sig) { - JAVASP_SERVER_INFO jsp_info = JAVASP_SERVER_INFO_INITIALIZER; + PL_SERVER_INFO pl_info = PL_SERVER_INFO_INITIALIZER; if (os_set_signal_handler (sig, SIG_DFL) == SIG_ERR) { @@ -330,16 +333,15 @@ static void javasp_signal_handler (int sig) return; } - int status = javasp_get_server_info (db_name, jsp_info); // if failed, - if (status == NO_ERROR && jsp_info.pid != JAVASP_PID_DISABLED) + int status = pl_get_server_info (db_name, pl_info); // if failed, + if (status == NO_ERROR && pl_info.pid != PL_PID_DISABLED) { - (void) envvar_bindir_file (executable_path, PATH_MAX, UTIL_JAVASP_NAME); if (command.compare ("running") != 0 || db_name.empty ()) { return; } - if (running_info.pid == jsp_info.pid && running_info.port == jsp_info.port) + if (running_info.pid == pl_info.pid && running_info.port == pl_info.port) { is_signal_handling = true; } @@ -348,68 +350,59 @@ static void javasp_signal_handler (int sig) return; } - int pid = fork (); - if (pid == 0) // child - { - execl (executable_path, UTIL_JAVASP_NAME, "start", db_name.c_str (), NULL); - exit (0); - } - else - { - // error handling in parent - std::string err_msg; + // error handling in parent + std::string err_msg; - void *addresses[64]; - int nn_addresses = backtrace (addresses, sizeof (addresses) / sizeof (void *)); - char **symbols = backtrace_symbols (addresses, nn_addresses); + void *addresses[64]; + int nn_addresses = backtrace (addresses, sizeof (addresses) / sizeof (void *)); + char **symbols = backtrace_symbols (addresses, nn_addresses); - err_msg += "pid ("; - err_msg += std::to_string (pid); - err_msg += ")\n"; + err_msg += "pid ("; + err_msg += std::to_string (getpid ()); + err_msg += ")\n"; - for (int i = 0; i < nn_addresses; i++) + for (int i = 0; i < nn_addresses; i++) + { + err_msg += symbols[i]; + if (i < nn_addresses - 1) { - err_msg += symbols[i]; - if (i < nn_addresses - 1) - { - err_msg += "\n"; - } + err_msg += "\n"; } - free (symbols); + } + free (symbols); - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_SERVER_CRASHED, 1, err_msg.c_str ()); + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_SERVER_CRASHED, 1, err_msg.c_str ()); - exit (1); - } + exit (1); } else { // resume signal hanlding - os_set_signal_handler (sig, javasp_signal_handler); + os_set_signal_handler (sig, pl_signal_handler); is_signal_handling = false; } } #endif static int -javasp_get_port_param () +pl_get_port_param () { int prm_port = 0; #if defined (WINDOWS) const bool is_uds_mode = false; #else - const bool is_uds_mode = prm_get_bool_value (PRM_ID_JAVA_STORED_PROCEDURE_UDS); + const bool is_uds_mode = prm_get_bool_value (PRM_ID_STORED_PROCEDURE_UDS); #endif - prm_port = (is_uds_mode) ? JAVASP_PORT_UDS_MODE : prm_get_integer_value (PRM_ID_JAVA_STORED_PROCEDURE_PORT); + prm_port = (is_uds_mode) ? PL_PORT_UDS_MODE : prm_get_integer_value (PRM_ID_STORED_PROCEDURE_PORT); return prm_port; } static int -javasp_start_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_name, const std::string &path) +pl_start_server (const PL_SERVER_INFO pl_info, const std::string &db_name, const std::string &path) { int status = NO_ERROR; - if (jsp_info.pid != JAVASP_PID_DISABLED && javasp_is_running (jsp_info.port, db_name)) + if (pl_info.pid != PL_PID_DISABLED && pl_is_running (pl_info, db_name)) { status = ER_GENERIC_ERROR; } @@ -420,14 +413,13 @@ javasp_start_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_na setsid (); #endif er_clear (); // clear error before string JVM - status = jsp_start_server (db_name.c_str (), path.c_str (), javasp_get_port_param ()); - + status = pl_start_jvm_server (db_name.c_str (), path.c_str (), pl_get_port_param ()); if (status == NO_ERROR) { - JAVASP_SERVER_INFO jsp_new_info { getpid(), jsp_server_port () }; + PL_SERVER_INFO pl_new_info { getpid(), pl_server_port () }; - javasp_unlink_info (db_name.c_str ()); - if ((javasp_open_info_dir () && javasp_write_info (db_name.c_str (), jsp_new_info))) + pl_unlink_info (db_name.c_str ()); + if ((pl_open_info_dir () && pl_write_info (db_name.c_str (), pl_new_info))) { /* succeed */ } @@ -435,7 +427,7 @@ javasp_start_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_na { /* failed to write info file */ char info_path[PATH_MAX], err_msg[PATH_MAX + 32]; - javasp_get_info_file (info_path, PATH_MAX, db_name.c_str ()); + pl_get_info_file (info_path, PATH_MAX, db_name.c_str ()); snprintf (err_msg, sizeof (err_msg), "Error while writing to file: (%s)", info_path); er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_START_JVM, 1, err_msg); status = ER_SP_CANNOT_START_JVM; @@ -447,77 +439,78 @@ javasp_start_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_na } static int -javasp_stop_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_name) +pl_stop_server (const PL_SERVER_INFO pl_info, const std::string &db_name) { - SOCKET socket = INVALID_SOCKET; - int status = NO_ERROR; +#define MAX_RETRY_COUNT 10 + int status = ER_FAILED; + int retry_count = 0; - socket = jsp_connect_server (db_name.c_str (), jsp_info.port); - if (socket != INVALID_SOCKET) + if (pl_info.pid != -1 && !is_terminated_process (pl_info.pid)) { - cubmethod::header header (DB_EMPTY_SESSION, SP_CODE_UTIL_TERMINATE_SERVER, 0); - status = mcon_send_data_to_java (socket, header); + terminate_process (pl_info.pid); - javasp_reset_info (db_name.c_str ()); - jsp_disconnect_server (socket); - - if (jsp_info.pid != -1 && !javasp_is_terminated_process (jsp_info.pid)) + while (retry_count < MAX_RETRY_COUNT) { - javasp_terminate_process (jsp_info.pid); + if (is_terminated_process (pl_info.pid) == true) + { + status = NO_ERROR; + break; + } + usleep (10); + retry_count++; } - - javasp_reset_info (db_name.c_str ()); } return status; } static int -javasp_status_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_name) +pl_status_server (const PL_SERVER_INFO pl_info, const std::string &db_name) { int status = NO_ERROR; - SOCKET socket = INVALID_SOCKET; cubmem::block buffer; - socket = jsp_connect_server (db_name.c_str(), jsp_info.port); - if (socket != INVALID_SOCKET) + cubpl::connection_pool connection_pool (1, db_name, pl_info.port, true); + cubpl::connection_view cv = connection_pool.claim (); + if (cv->is_valid()) { cubmethod::header header (DB_EMPTY_SESSION, SP_CODE_UTIL_STATUS, 0); - status = mcon_send_data_to_java (socket, header); + status = cv->send_buffer_args (header); if (status != NO_ERROR) { goto exit; } - status = cubmethod::mcon_read_data_from_java (socket, buffer); + status = cv->receive_buffer (buffer); if (status != NO_ERROR) { goto exit; } - int num_args = 0; - JAVASP_STATUS_INFO status_info; + if (status == NO_ERROR) + { + int num_args = 0; + PL_STATUS_INFO status_info; - status_info.pid = jsp_info.pid; + status_info.pid = pl_info.pid; - packing_unpacker unpacker (buffer.ptr, buffer.dim); + packing_unpacker unpacker (buffer.ptr, buffer.dim); - unpacker.unpack_int (status_info.port); - unpacker.unpack_string (status_info.db_name); - unpacker.unpack_int (num_args); - std::string arg; - for (int i = 0; i < num_args; i++) - { - unpacker.unpack_string (arg); - status_info.vm_args.push_back (arg); - } + unpacker.unpack_int (status_info.port); + unpacker.unpack_string (status_info.db_name); + unpacker.unpack_int (num_args); + std::string arg; + for (int i = 0; i < num_args; i++) + { + unpacker.unpack_string (arg); + status_info.vm_args.push_back (arg); + } - javasp_dump_status (stdout, status_info); + pl_dump_status (stdout, status_info); + } } exit: - jsp_disconnect_server (socket); - if (buffer.ptr) { free_and_init (buffer.ptr); @@ -527,23 +520,24 @@ javasp_status_server (const JAVASP_SERVER_INFO jsp_info, const std::string &db_n } static int -javasp_ping_server (const int server_port, const char *db_name, char *buf) +pl_ping_server (const PL_SERVER_INFO pl_info, const char *db_name, char *buf) { int status = NO_ERROR; - SOCKET socket = INVALID_SOCKET; cubmem::block ping_blk {0, NULL}; - socket = jsp_connect_server (db_name, server_port); - if (socket != INVALID_SOCKET) + cubpl::connection_pool connection_pool (1, db_name, pl_info.port, true); + cubpl::connection_view cv = connection_pool.claim (); + + if (cv->is_valid()) { cubmethod::header header (DB_EMPTY_SESSION, SP_CODE_UTIL_PING, 0); - status = mcon_send_data_to_java (socket, header); + status = cv->send_buffer_args (header); if (status != NO_ERROR) { goto exit; } - status = cubmethod::mcon_read_data_from_java (socket, ping_blk); + status = cv->receive_buffer (ping_blk); if (status != NO_ERROR) { goto exit; @@ -557,14 +551,13 @@ javasp_ping_server (const int server_port, const char *db_name, char *buf) delete [] ping_blk.ptr; } - jsp_disconnect_server (socket); return er_errid (); } static void -javasp_dump_status (FILE *fp, JAVASP_STATUS_INFO status_info) +pl_dump_status (FILE *fp, PL_STATUS_INFO status_info) { - if (status_info.port == JAVASP_PORT_UDS_MODE) + if (status_info.port == PL_PORT_UDS_MODE) { fprintf (fp, "Java Stored Procedure Server (%s, pid %d, UDS)\n", status_info.db_name.c_str (), status_info.pid); } @@ -587,12 +580,12 @@ javasp_dump_status (FILE *fp, JAVASP_STATUS_INFO status_info) } static bool -javasp_is_running (const int server_port, const std::string &db_name) +pl_is_running (const PL_SERVER_INFO pl_info, const std::string &db_name) { // check server running bool result = false; - char buffer[JAVASP_PING_LEN] = {0}; - if (javasp_ping_server (server_port, db_name.c_str (), buffer) == NO_ERROR) + char buffer[PL_PING_LEN] = {0}; + if (pl_ping_server (pl_info, db_name.c_str (), buffer) == NO_ERROR) { if (db_name.compare (0, db_name.size (), buffer) == 0) { @@ -602,62 +595,11 @@ javasp_is_running (const int server_port, const std::string &db_name) return result; } -/* - * javasp_is_terminated_process () - - * return: - * pid(in): - * TODO there exists same function in file_io.c and util_service.c - */ -static bool -javasp_is_terminated_process (int pid) -{ -#if defined(WINDOWS) - HANDLE h_process; - - h_process = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid); - if (h_process == NULL) - { - return true; - } - else - { - CloseHandle (h_process); - return false; - } -#else /* WINDOWS */ - if (kill (pid, 0) == -1) - { - return true; - } - else - { - return false; - } -#endif /* WINDOWS */ -} - -static void -javasp_terminate_process (int pid) -{ -#if defined(WINDOWS) - HANDLE phandle; - - phandle = OpenProcess (PROCESS_TERMINATE, FALSE, pid); - if (phandle) - { - TerminateProcess (phandle, 0); - CloseHandle (phandle); - } -#else /* ! WINDOWS */ - kill (pid, SIGTERM); -#endif /* ! WINDOWS */ -} - static int -javasp_get_server_info (const std::string &db_name, JAVASP_SERVER_INFO &info) +pl_get_server_info (const std::string &db_name, PL_SERVER_INFO &info) { - if (javasp_open_info_dir () - && javasp_read_info (db_name.c_str(), info)) + if (pl_open_info_dir () + && pl_read_info (db_name.c_str(), info)) { return NO_ERROR; } @@ -668,7 +610,7 @@ javasp_get_server_info (const std::string &db_name, JAVASP_SERVER_INFO &info) } static int -javasp_check_database (const std::string &db_name, std::string &path) +pl_check_database (const std::string &db_name, std::string &path) { int status = NO_ERROR; @@ -688,7 +630,7 @@ javasp_check_database (const std::string &db_name, std::string &path) } static int -javasp_check_argument (int argc, char *argv[], std::string &command, std::string &db_name) +pl_check_argument (int argc, char *argv[], std::string &command, std::string &db_name) { int status = NO_ERROR; @@ -706,7 +648,7 @@ javasp_check_argument (int argc, char *argv[], std::string &command, std::string else { status = ER_GENERIC_ERROR; - JAVASP_PRINT_ERR_MSG ("Invalid number of arguments: %d\n", argc); + PL_PRINT_ERR_MSG ("Invalid number of arguments: %d\n", argc); } if (status == NO_ERROR) @@ -717,7 +659,7 @@ javasp_check_argument (int argc, char *argv[], std::string &command, std::string if (it == commands.end()) { status = ER_GENERIC_ERROR; - JAVASP_PRINT_ERR_MSG ("Invalid command: %s\n", command.c_str ()); + PL_PRINT_ERR_MSG ("Invalid command: %s\n", command.c_str ()); } } diff --git a/src/executables/plcsql.cpp b/src/executables/plcsql.cpp index 44cea5b07e8..f07325b72e6 100644 --- a/src/executables/plcsql.cpp +++ b/src/executables/plcsql.cpp @@ -49,7 +49,7 @@ static std::string input_string; static bool verbose = false; // output -static PLCSQL_COMPILE_INFO compile_info; +static PLCSQL_COMPILE_RESPONSE compile_response; #define DB_PLCSQL_AS_ARGS(arg) \ arg.db_name.data(), arg.user_name.data(), arg.passwd.data(), NULL, DB_CLIENT_TYPE_PLCSQL_HELPER @@ -254,31 +254,37 @@ main (int argc, char *argv[]) PLCSQL_LOG ("[Compile PL/CSQL]"); /* Call network interface API to send a input file (PL/CSQL program) */ - if (plcsql_transfer_file (input_string, verbose, compile_info) != NO_ERROR) + + PLCSQL_COMPILE_REQUEST compile_request; + compile_request.code = input_string; + compile_request.mode = (verbose == true) ? "v" : ""; + compile_request.owner = "DBA"; // dummy + + if (plcsql_transfer_file (compile_request, compile_response) != NO_ERROR) { PLCSQL_LOG ("Transferring or Translating PL/CSQL program is failed"); goto exit_on_end; } - if (compile_info.err_code == 0) + if (compile_response.err_code == 0) { PLCSQL_LOG ("[Output File]"); - PLCSQL_LOG (compile_info.translated_code); + PLCSQL_LOG (compile_response.translated_code); PLCSQL_LOG ("[Stored Routine Definition]"); - PLCSQL_LOG (compile_info.register_stmt); + PLCSQL_LOG (compile_response.register_stmt); } else { PLCSQL_LOG ("[Compile Error Info]"); - PLCSQL_LOG ("error at : " << compile_info.err_line); - PLCSQL_LOG ("error message : " << compile_info.err_msg); + PLCSQL_LOG ("error at : " << compile_response.err_line); + PLCSQL_LOG ("error message : " << compile_response.err_msg); goto exit_on_end; } // Execute SQL { - const std::string &sql = compile_info.register_stmt; + const std::string &sql = compile_response.register_stmt; if (sql.empty ()) { PLCSQL_LOG_FORCE ("Invalid SQL string"); diff --git a/src/executables/server.c b/src/executables/server.c index c021d456ac6..431e24a4c1b 100644 --- a/src/executables/server.c +++ b/src/executables/server.c @@ -50,7 +50,6 @@ #include "system_parameter.h" #include "perf_monitor.h" #include "util_func.h" -#include "connection_sr.h" #if defined(WINDOWS) #include "wintcp.h" #else /* !defined (WINDOWS) */ @@ -207,6 +206,8 @@ CreateMiniDump (struct _EXCEPTION_POINTERS *pException, char *db_name) static void crash_handler (int signo, siginfo_t * siginfo, void *dummyp) { + int pid; + if (signo != SIGABRT && siginfo != NULL && siginfo->si_code <= 0) { register_fatal_signal_handler (signo); @@ -217,6 +218,47 @@ crash_handler (int signo, siginfo_t * siginfo, void *dummyp) { return; } + + if (!BO_IS_SERVER_RESTARTED () || !prm_get_bool_value (PRM_ID_AUTO_RESTART_SERVER)) + { + return; + } + + pid = fork (); + if (pid == 0) + { + char err_log[PATH_MAX]; + int ppid; + int fd, fd_max; + + fd_max = css_get_max_socket_fds (); + + for (fd = 3; fd < fd_max; fd++) + { + close (fd); + } + + ppid = getppid (); + while (1) + { + if (kill (ppid, 0) < 0) + { + break; + } + sleep (1); + } + + unmask_signal (signo); + + if (prm_get_string_value (PRM_ID_ER_LOG_FILE) != NULL) + { + snprintf (err_log, PATH_MAX, "%s.%d", prm_get_string_value (PRM_ID_ER_LOG_FILE), ppid); + rename (prm_get_string_value (PRM_ID_ER_LOG_FILE), err_log); + } + + execl (executable_path, executable_path, database_name, NULL); + exit (0); + } } #if !defined (NDEBUG) @@ -312,9 +354,6 @@ main (int argc, char **argv) hb_set_exec_path (executable_path); hb_set_argv (argv); - css_set_exec_path (executable_path); - css_set_argv (argv); - /* create a new session */ setsid (); #endif diff --git a/src/executables/unload_object.c b/src/executables/unload_object.c index afd3ebc55c4..5e982ad6723 100644 --- a/src/executables/unload_object.c +++ b/src/executables/unload_object.c @@ -133,6 +133,7 @@ static const char *prohibited_classes[] = { CT_DATATYPE_NAME, CT_STORED_PROC_NAME, CT_STORED_PROC_ARGS_NAME, + CT_STORED_PROC_CODE_NAME, CT_PARTITION_NAME, CT_COLLATION_NAME, CT_CHARSET_NAME, diff --git a/src/executables/unload_schema.c b/src/executables/unload_schema.c index 1ae4e096fa6..c0c5035092c 100644 --- a/src/executables/unload_schema.c +++ b/src/executables/unload_schema.c @@ -58,6 +58,7 @@ #include "object_print.h" #include "dbtype.h" #include "tde.h" +#include "sp_catalog.hpp" #define CLASS_NAME_MAX 80 @@ -158,9 +159,8 @@ typedef enum typedef enum { - SYNONYM_NAME, + SYNONYM_UNIQUE_NAME, SYNONYM_OWNER, - SYNONYM_OWNER_NAME, SYNONYM_IS_PUBLIC, SYNONYM_TARGET_NAME, SYNONYM_TARGET_OWNER_NAME, @@ -231,8 +231,13 @@ static void emit_method_def (extract_context & ctxt, print_output & output_ctx, static void emit_methfile_def (print_output & output_ctx, DB_METHFILE * methfile); static void emit_partition_parts (print_output & output_ctx, SM_PARTITION * partition_info, int partcnt); static void emit_partition_info (extract_context & ctxt, print_output & output_ctx, MOP clsobj); + +static int emit_stored_procedure_pre (extract_context & ctxt, print_output & output_ctx); +static int emit_stored_procedure_post (extract_context & ctxt, print_output & output_ctx); static int emit_stored_procedure_args (print_output & output_ctx, int arg_cnt, DB_SET * arg_set); -static int emit_stored_procedure (extract_context & ctxt, print_output & output_ctx); +static int emit_stored_procedure_code (extract_context & ctxt, print_output & output_ctx, const char *code_name, + const char *owner_name, DB_VALUE * comment); + static int emit_foreign_key (extract_context & ctxt, print_output & output_ctx, DB_OBJLIST * classes); static int emit_grant (extract_context & ctxt, print_output & output_ctx, DB_OBJLIST * classes); static void emit_unique_key (extract_context & ctxt, print_output & output_ctx, DB_OBJLIST * classes); @@ -266,7 +271,6 @@ static int create_filename_schema_info (const char *output_dirname, const char * const size_t filename_size); static void str_tolower (char *str); -static bool is_builtin_package_function (const char *sp_name); static PARSER_VARCHAR *do_recreate_where_clause_or_function_attr (PARSER_CONTEXT ** parser, const char *class_name, DB_CONSTRAINT * constraint, bool where_clause); @@ -1126,9 +1130,11 @@ export_synonym (extract_context & ctxt, print_output & output_ctx) DB_QUERY_RESULT *query_result; DB_QUERY_ERROR query_error; DB_VALUE values[SYNONYM_VALUE_INDEX_MAX]; - const char *synonym_name = NULL; + char *synonym_name = NULL; DB_OBJECT *synonym_owner = NULL; - const char *synonym_owner_name = NULL; + const char *synonym_unique_name = NULL; + char synonym_owner_name[DB_MAX_IDENTIFIER_LENGTH]; + synonym_owner_name[0] = '\0'; int is_public = 0; const char *target_name = NULL; const char *target_owner_name = NULL; @@ -1141,29 +1147,28 @@ export_synonym (extract_context & ctxt, print_output & output_ctx) size_t uppercase_user_size = 0; size_t query_size = 0; char *query = NULL; - char output_owner[DB_MAX_USER_LENGTH + 4] = { '\0' }; + char synonym_output_owner[DB_MAX_USER_LENGTH + 4]; + synonym_output_owner[0] = '\0'; DB_OBJLIST *cl = NULL; const char *name = NULL; - char temp_schema[DB_MAX_CLASS_LENGTH] = { '\0' }; + char temp_schema[DB_MAX_IDENTIFIER_LENGTH] = { '\0' }; // *INDENT-OFF* - const char *query_all = "SELECT [name], " - "[owner], " - "[owner].[name], " + const char *query_all = "SELECT [unique_name], " + "[owner], " + "[is_public], " + "[target_name], " + "DECODE((SELECT 1 from [_db_class] WHERE [class_name] = [target_name] and [is_system_class] = 1), NULL, LOWER([target_owner].[name]), '') target_owner, " + "[comment] " + "FROM [_db_synonym]"; + + const char *query_user = "SELECT [unique_name], " + "[owner], " "[is_public], " "[target_name], " - "[target_owner].[name], " + "DECODE((SELECT 1 from [_db_class] WHERE [class_name] = [target_name] and [is_system_class] = 1), NULL, LOWER([target_owner].[name]), '') target_owner, " "[comment] " - "FROM [_db_synonym]"; - - const char *query_user = "SELECT [name], " - "[owner], " - "[owner].[name], " - "[is_public], " - "[target_name], " - "[target_owner].[name], " - "[comment] " - "FROM [_db_synonym]" + "FROM [_db_synonym]"; "WHERE [owner].[name] = '%s'"; // *INDENT-ON* @@ -1225,8 +1230,7 @@ export_synonym (extract_context & ctxt, print_output & output_ctx) /* Validation of the result value */ switch (i) { - case SYNONYM_NAME: - case SYNONYM_OWNER_NAME: + case SYNONYM_UNIQUE_NAME: case SYNONYM_TARGET_NAME: case SYNONYM_TARGET_OWNER_NAME: { @@ -1274,9 +1278,8 @@ export_synonym (extract_context & ctxt, print_output & output_ctx) } } - synonym_name = db_get_string (&values[SYNONYM_NAME]); + synonym_unique_name = db_get_string (&values[SYNONYM_UNIQUE_NAME]); synonym_owner = db_get_object (&values[SYNONYM_OWNER]); - synonym_owner_name = db_get_string (&values[SYNONYM_OWNER_NAME]); is_public = db_get_int (&values[SYNONYM_IS_PUBLIC]); target_name = db_get_string (&values[SYNONYM_TARGET_NAME]); target_owner_name = db_get_string (&values[SYNONYM_TARGET_OWNER_NAME]); @@ -1293,8 +1296,7 @@ export_synonym (extract_context & ctxt, print_output & output_ctx) { name = db_get_class_name (cl->op); - str_tolower ((char *) target_owner_name); - snprintf (temp_schema, DB_MAX_CLASS_LENGTH, "%s%s%s", (target_owner_name), ".", target_name); + snprintf (temp_schema, DB_MAX_IDENTIFIER_LENGTH, "%s%s%s", (target_owner_name), ".", target_name); if (strcmp (temp_schema, name) == 0) { @@ -1319,12 +1321,20 @@ export_synonym (extract_context & ctxt, print_output & output_ctx) output_ctx ("CREATE PRIVATE"); } - PRINT_OWNER_NAME (synonym_owner_name, (ctxt.is_dba_user || ctxt.is_dba_group_member), output_owner, - sizeof (output_owner)); + SPLIT_USER_SPECIFIED_NAME (synonym_unique_name, synonym_owner_name, synonym_name); + PRINT_OWNER_NAME (synonym_owner_name, (ctxt.is_dba_user || ctxt.is_dba_group_member), synonym_output_owner, + sizeof (synonym_owner_name)); + + output_ctx (" SYNONYM %s%s%s%s FOR ", synonym_output_owner, PRINT_IDENTIFIER (synonym_name)); - output_ctx (" SYNONYM %s%s%s%s FOR %s%s%s.%s%s%s", output_owner, - PRINT_IDENTIFIER (synonym_name), PRINT_IDENTIFIER (target_owner_name), - PRINT_IDENTIFIER (target_name)); + if (target_owner_name[0] == 0x00) + { + output_ctx ("%s%s%s", PRINT_IDENTIFIER (target_name)); + } + else + { + output_ctx ("%s%s%s.%s%s%s", PRINT_IDENTIFIER (target_owner_name), PRINT_IDENTIFIER (target_name)); + } if (DB_IS_NULL (&values[SYNONYM_COMMENT]) == false) { @@ -1434,7 +1444,7 @@ extract_schema (extract_context & ctxt, print_output & schema_output_ctx) err_count++; } - if (required_class_only == false && emit_stored_procedure (ctxt, schema_output_ctx) != NO_ERROR) + if (required_class_only == false && emit_stored_procedure_pre (ctxt, schema_output_ctx) != NO_ERROR) { err_count++; } @@ -1491,6 +1501,11 @@ extract_schema (extract_context & ctxt, print_output & schema_output_ctx) err_count++; } + if (required_class_only == false && emit_stored_procedure_post (ctxt, schema_output_ctx) != NO_ERROR) + { + err_count++; + } + if (ctxt.classes != NULL && (emit_foreign_key (ctxt, schema_output_ctx, ctxt.classes) != NO_ERROR)) { err_count++; @@ -4307,34 +4322,6 @@ emit_partition_info (extract_context & ctxt, print_output & output_ctx, MOP clso output_ctx (";\n"); } -// TODO: quick fix -static bool -is_builtin_package_function (const char *sp_name) -{ - static const char *builtin_list[] = { - "enable", - "disable", - "put", - "put_line", - "new_line", - "get_line", - "get_lines", - NULL - }; - - int dim, i; - - dim = DIM (builtin_list); - for (i = 0; i < dim; i++) - { - if (builtin_list[i] != NULL && strcasecmp (builtin_list[i], sp_name) == 0) - { - return true; - } - } - return false; -} - /* * emit_stored_procedure_args - emit stored procedure arguments * return: 0 if success, error count otherwise @@ -4407,21 +4394,26 @@ emit_stored_procedure_args (print_output & output_ctx, int arg_cnt, DB_SET * arg } /* - * emit_stored_procedure - emit stored procedure + * emit_stored_procedure_pre - emit stored procedure (Dummy PL/CSQL and Java SP) * return: void * output_ctx(in/out): output context */ static int -emit_stored_procedure (extract_context & ctxt, print_output & output_ctx) +emit_stored_procedure_pre (extract_context & ctxt, print_output & output_ctx) { MOP cls, obj, owner; DB_OBJLIST *sp_list = NULL, *cur_sp; - DB_VALUE sp_name_val, sp_type_val, arg_cnt_val, args_val, rtn_type_val, method_val, comment_val; + DB_VALUE unique_name_val, sp_name_val, pkg_name_val, sp_type_val, arg_cnt_val, lang_val, generated_val, args_val, + rtn_type_val, class_val, method_val, directive_val, comment_val; DB_VALUE owner_val, owner_name_val; - int sp_type, rtn_type, arg_cnt, save; + int sp_type, rtn_type, arg_cnt, directive, save; DB_SET *arg_set; int err; int err_count = 0; + char owner_name[DB_MAX_USER_LENGTH]; + owner_name[0] = '\0'; + char output_owner[DB_MAX_USER_LENGTH + 4]; + output_owner[0] = '\0'; AU_DISABLE (save); @@ -4437,45 +4429,72 @@ emit_stored_procedure (extract_context & ctxt, print_output & output_ctx) { obj = cur_sp->op; - if ((err = db_get (obj, SP_ATTR_SP_TYPE, &sp_type_val)) != NO_ERROR - || (err = db_get (obj, SP_ATTR_NAME, &sp_name_val)) != NO_ERROR - || (err = db_get (obj, SP_ATTR_ARG_COUNT, &arg_cnt_val)) != NO_ERROR - || (err = db_get (obj, SP_ATTR_ARGS, &args_val)) != NO_ERROR - || ((err = db_get (obj, SP_ATTR_RETURN_TYPE, &rtn_type_val)) != NO_ERROR) - || (err = db_get (obj, SP_ATTR_TARGET, &method_val)) != NO_ERROR - || (err = db_get (obj, SP_ATTR_OWNER, &owner_val)) != NO_ERROR - || (err = db_get (obj, SP_ATTR_COMMENT, &comment_val)) != NO_ERROR) + if ((err = db_get (obj, SP_ATTR_IS_SYSTEM_GENERATED, &generated_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_LANG, &lang_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_OWNER, &owner_val)) != NO_ERROR) { err_count++; continue; } - const char *sp_name = db_get_string (&sp_name_val); - if (is_builtin_package_function (sp_name)) + if (db_get_int (&generated_val) == 1) { continue; } - if (ctxt.is_dba_user == false && ctxt.is_dba_group_member == false) + // owner + owner = db_get_object (&owner_val); + err = db_get (owner, "name", &owner_name_val); + if (err != NO_ERROR) { - owner = db_get_object (&owner_val); - err = db_get (owner, "name", &owner_name_val); - if (err != NO_ERROR) - { - err_count++; - continue; - } + err_count++; + continue; + } + if (ctxt.is_dba_user == false && ctxt.is_dba_group_member == false) + { if (strcasecmp (ctxt.login_user, db_get_string (&owner_name_val)) != 0) { + db_value_clear (&owner_name_val); continue; } } + if ((err = db_get (obj, SP_ATTR_SP_TYPE, &sp_type_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_UNIQUE_NAME, &unique_name_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_NAME, &sp_name_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_PKG, &pkg_name_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_ARG_COUNT, &arg_cnt_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_ARGS, &args_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_RETURN_TYPE, &rtn_type_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_DIRECTIVE, &directive_val)) != NO_ERROR) + { + err_count++; + continue; + } + sp_type = db_get_int (&sp_type_val); + output_ctx ("\nCREATE %s", sp_type == SP_TYPE_PROCEDURE ? "PROCEDURE" : "FUNCTION"); - output_ctx (" %s%s%s (", PRINT_IDENTIFIER (db_get_string (&sp_name_val))); + // unique_name + const char *unique_name = db_get_string (&unique_name_val); + // sp_name + const char *sp_name = db_get_string (&sp_name_val); + sm_qualifier_name (unique_name, owner_name, DB_MAX_USER_LENGTH); + PRINT_OWNER_NAME (owner_name, (ctxt.is_dba_user || ctxt.is_dba_group_member), output_owner, + sizeof (output_owner)); + + if (!DB_IS_NULL (&pkg_name_val)) + { + const char *pkg_name = db_get_string (&pkg_name_val); + output_ctx (" %s%s%s.%s%s%s (", PRINT_IDENTIFIER (pkg_name), PRINT_IDENTIFIER (sp_name)); + db_value_clear (&pkg_name_val); + } + else + { + output_ctx (" %s%s%s%s (", output_owner, PRINT_IDENTIFIER (sp_name)); + } arg_cnt = db_get_int (&arg_cnt_val); arg_set = db_get_set (&args_val); @@ -4501,16 +4520,104 @@ emit_stored_procedure (extract_context & ctxt, print_output & output_ctx) } } - output_ctx ("AS LANGUAGE JAVA NAME '%s'", db_get_string (&method_val)); + // authid + directive = db_get_int (&directive_val); + if (directive & SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_CALLER) + { + output_ctx ("AUTHID CALLER "); + } + else + { + output_ctx ("AUTHID OWNER "); + } - if (!DB_IS_NULL (&comment_val)) + int sp_lang = db_get_int (&lang_val); + if (sp_lang == SP_LANG_PLCSQL) { - output_ctx (" COMMENT "); - desc_value_print (output_ctx, &comment_val); + output_ctx ("AS LANGUAGE PLCSQL BEGIN "); + output_ctx + ("RAISE_APPLICATION_ERROR(1000, '%s%s%s%s: incomplete during loaddb'); /* __CUBRID_NO_BODY__ */", + output_owner, PRINT_IDENTIFIER (sp_name)); + output_ctx (" END;\n"); } + else + { + if ((err = db_get (obj, SP_ATTR_TARGET_CLASS, &class_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_TARGET_METHOD, &method_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_COMMENT, &comment_val)) != NO_ERROR) + { + err_count++; + continue; + } - output_ctx (";\n"); + output_ctx ("AS LANGUAGE JAVA NAME '%s.%s'", db_get_string (&class_val), db_get_string (&method_val)); + db_value_clear (&class_val); + db_value_clear (&method_val); + if (!DB_IS_NULL (&comment_val)) + { + output_ctx (" COMMENT "); + desc_value_print (output_ctx, &comment_val); + } + + output_ctx (";\n"); + } + db_value_clear (&sp_name_val); + db_value_clear (&unique_name_val); + db_value_clear (&owner_name_val); + } + + db_objlist_free (sp_list); + AU_ENABLE (save); + + return err_count; +} + +/* + * emit_stored_procedure_post - emit stored procedure + * return: void + * output_ctx(in/out): output context + */ +static int +emit_stored_procedure_post (extract_context & ctxt, print_output & output_ctx) +{ + MOP cls, obj, owner; + DB_OBJLIST *sp_list = NULL, *cur_sp; + DB_VALUE lang_val, owner_val, owner_name_val, generated_val, class_val, comment_val; + int save; + int err; + int err_count = 0; + const char *owner_name; + + AU_DISABLE (save); + + cls = db_find_class (SP_CLASS_NAME); + if (cls == NULL) + { + AU_ENABLE (save); + return 1; + } + + sp_list = db_get_all_objects (cls); + for (cur_sp = sp_list; cur_sp; cur_sp = cur_sp->next) + { + obj = cur_sp->op; + + if ((err = db_get (obj, SP_ATTR_IS_SYSTEM_GENERATED, &generated_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_LANG, &lang_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_OWNER, &owner_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_COMMENT, &comment_val)) != NO_ERROR) + { + err_count++; + continue; + } + + if (db_get_int (&generated_val) == 1) + { + continue; + } + + // owner owner = db_get_object (&owner_val); err = db_get (owner, "name", &owner_name_val); if (err != NO_ERROR) @@ -4519,10 +4626,35 @@ emit_stored_procedure (extract_context & ctxt, print_output & output_ctx) continue; } - if (ctxt.is_dba_user || ctxt.is_dba_group_member) + owner_name = db_get_string (&owner_name_val); + if (ctxt.is_dba_user == false && ctxt.is_dba_group_member == false) { - output_ctx ("call [change_sp_owner]('%s', '%s') on class [db_root];\n", db_get_string (&sp_name_val), - db_get_string (&owner_name_val)); + if (strcasecmp (ctxt.login_user, owner_name) != 0) + { + db_value_clear (&owner_name_val); + continue; + } + } + + int sp_lang = db_get_int (&lang_val); + if (sp_lang == SP_LANG_PLCSQL) + { + if ((err = db_get (obj, SP_ATTR_TARGET_CLASS, &class_val)) != NO_ERROR) + { + err_count++; + continue; + } + + const char *target_class = db_get_string (&class_val); + err = emit_stored_procedure_code (ctxt, output_ctx, target_class, owner_name, &comment_val); + output_ctx ("\n"); + + db_value_clear (&class_val); + if (err > 0) + { + err_count++; + continue; + } } db_value_clear (&owner_name_val); @@ -4534,6 +4666,112 @@ emit_stored_procedure (extract_context & ctxt, print_output & output_ctx) return err_count; } +/* + * emit_stored_procedure_code - emit stored procedure code + * return: 0 if success, error count otherwise + * code_name(in): code name + * owner_name(in): owner name + */ +static int +emit_stored_procedure_code (extract_context & ctxt, print_output & output_ctx, const char *code_name, + const char *owner_name, DB_VALUE * comment) +{ + MOP obj; + int save, err = NO_ERROR; + DB_VALUE value, stype_val, scode_val; + int stype; + PARSER_CONTEXT *parser = NULL; + PT_NODE **scode_ptr; + char *scode_ptr_result = NULL; + char downcase_owner_name[DB_MAX_USER_LENGTH]; + downcase_owner_name[0] = '\0'; + + AU_DISABLE (save); + + db_make_string (&value, code_name); + obj = db_find_unique (db_find_class (SP_CODE_CLASS_NAME), SP_ATTR_CLS_NAME, &value); + if (obj == NULL) + { + err = ER_FAILED; + goto exit; + } + + + if ((err = db_get (obj, SP_ATTR_SOURCE_TYPE, &stype_val)) != NO_ERROR + || (err = db_get (obj, SP_ATTR_SOURCE_CODE, &scode_val)) != NO_ERROR) + { + goto exit; + } + + stype = db_get_int (&stype_val); + if (stype == SPSC_PLCSQL) + { + const char *scode = db_get_string (&scode_val); + parser = parser_create_parser (); + if (parser == NULL) + { + err = ER_FAILED; + goto exit; + } + + scode_ptr = parser_parse_string (parser, scode); + if (scode_ptr != NULL) + { + if (ctxt.is_dba_user == false && ctxt.is_dba_group_member == false) + { + parser->custom_print |= PT_PRINT_NO_CURRENT_USER_NAME; + } + else + { + PT_NODE *sp_name = (*scode_ptr)->info.sp.name; + if (sp_name->info.name.resolved == NULL) + { + sm_downcase_name (owner_name, downcase_owner_name, DB_MAX_USER_LENGTH); + sp_name->info.name.resolved = pt_append_string (parser, NULL, downcase_owner_name); + } + } + + parser->flag.is_parsing_unload_schema = 1; + scode_ptr_result = parser_print_tree_with_quotes (parser, *scode_ptr); + } + + if (scode_ptr_result) + { + output_ctx ("\n%s", scode_ptr_result); + if (!DB_IS_NULL (comment)) + { + if ((*scode_ptr)->info.sp.comment == NULL) + { + output_ctx ("\nCOMMENT "); + } + else + { + output_ctx ("COMMENT "); + } + desc_value_print (output_ctx, comment); + } + } + else + { + output_ctx ("\n/* error occurs: %s \n\n %s; \n*/", parser->error_buffer ? parser->error_buffer : "", scode); + } + } + output_ctx (";"); + +exit: + + if (parser) + { + parser_free_parser (parser); + } + + db_value_clear (&value); + db_value_clear (&scode_val); + AU_ENABLE (save); + + return err; +} + /* * emit_foreign_key - emit foreign key * return: NO_ERROR if successful, error code otherwise @@ -5163,7 +5401,12 @@ extract_procedure (extract_context & ctxt) if (required_class_only == false) { - err = emit_stored_procedure (ctxt, output_ctx); + err = emit_stored_procedure_pre (ctxt, output_ctx); + } + + if (required_class_only == false) + { + err = emit_stored_procedure_post (ctxt, output_ctx); } fflush (output_file); @@ -5792,8 +6035,9 @@ static int emit_grant (extract_context & ctxt, print_output & output_ctx, DB_OBJLIST * classes) { int err = NO_ERROR; - DB_OBJLIST *cl; + DB_OBJLIST *cl, *cls, *sp_list = NULL; const char *name; + MOP sp_owner; int is_partitioned = 0; if (ctxt.do_auth) @@ -5805,7 +6049,21 @@ emit_grant (extract_context & ctxt, print_output & output_ctx, DB_OBJLIST * clas { continue; } - err = au_export_grants (ctxt, output_ctx, cl->op); + err = au_export_grants (ctxt, output_ctx, cl->op, DB_OBJECT_CLASS); + } + + sp_list = db_get_all_objects (db_find_class (SP_CLASS_NAME)); + for (cls = sp_list; cls; cls = cls->next) + { + if (!(ctxt.is_dba_user || ctxt.is_dba_group_member)) + { + sp_owner = jsp_get_owner (cls->op); + if (!ws_is_same_object (sp_owner, Au_user)) + { + continue; + } + } + err = au_export_grants (ctxt, output_ctx, cls->op, DB_OBJECT_PROCEDURE); } } @@ -5904,11 +6162,6 @@ extract_split_schema_files (extract_context & ctxt) err_count++; } - if (extract_procedure (ctxt) != NO_ERROR) - { - err_count++; - } - if (extract_server (ctxt) != NO_ERROR) { err_count++; @@ -5939,6 +6192,11 @@ extract_split_schema_files (extract_context & ctxt) err_count++; } + if (extract_procedure (ctxt) != NO_ERROR) + { + err_count++; + } + if (extract_pk (ctxt) != NO_ERROR) { err_count++; diff --git a/src/executables/unloaddb.c b/src/executables/unloaddb.c index 05d488089d9..94ff8b90e4b 100644 --- a/src/executables/unloaddb.c +++ b/src/executables/unloaddb.c @@ -263,8 +263,6 @@ unloaddb (UTIL_FUNCTION_ARG * arg) snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, exec_name); er_init (er_msg_file, ER_NEVER_EXIT); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - /* support for SUPPORT_DEDUPLICATE_KEY_MODE */ sysprm_set_force (prm_get_name (PRM_ID_PRINT_INDEX_DETAIL), utility_get_option_bool_value (arg_map, UNLOAD_SKIP_INDEX_DETAIL_S) ? "no" : "yes"); diff --git a/src/executables/util_cs.c b/src/executables/util_cs.c index e97863db6fe..b6e83d6e0d7 100644 --- a/src/executables/util_cs.c +++ b/src/executables/util_cs.c @@ -263,8 +263,6 @@ backupdb (UTIL_FUNCTION_ARG * arg) snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name); er_init (er_msg_file, ER_NEVER_EXIT); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); /* disable authorization for this operation */ db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); db_login ("DBA", NULL); @@ -482,7 +480,6 @@ addvoldb (UTIL_FUNCTION_ARG * arg) /* tuning system parameters */ sysprm_set_force (prm_get_name (PRM_ID_PB_NBUFFERS), "1024"); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); @@ -786,8 +783,6 @@ checkdb (UTIL_FUNCTION_ARG * arg) snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name); er_init (er_msg_file, ER_NEVER_EXIT); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); db_login ("DBA", NULL); @@ -973,7 +968,6 @@ spacedb (UTIL_FUNCTION_ARG * arg) /* tuning system parameters */ sysprm_set_force (prm_get_name (PRM_ID_PB_NBUFFERS), "1024"); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); /* should have little copyright herald message ? */ AU_DISABLE_PASSWORDS (); @@ -2293,8 +2287,6 @@ paramdump (UTIL_FUNCTION_ARG * arg) snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name); er_init (er_msg_file, ER_NEVER_EXIT); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - #if defined (CS_MODE) /* should have little copyright herald message ? */ AU_DISABLE_PASSWORDS (); @@ -3672,8 +3664,6 @@ vacuumdb (UTIL_FUNCTION_ARG * arg) snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name); er_init (er_msg_file, ER_NEVER_EXIT); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); if (dump_flag) { diff --git a/src/executables/util_sa.c b/src/executables/util_sa.c index fab2803d74e..0027979cf3c 100644 --- a/src/executables/util_sa.c +++ b/src/executables/util_sa.c @@ -634,7 +634,6 @@ createdb (UTIL_FUNCTION_ARG * arg) /* tuning system parameters */ sysprm_set_force (prm_get_name (PRM_ID_PB_NBUFFERS), "1024"); sysprm_set_force (prm_get_name (PRM_ID_XASL_CACHE_MAX_ENTRIES), "-1"); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); sysprm_set_force (prm_get_name (PRM_ID_SUPPLEMENTAL_LOG), "0"); AU_DISABLE_PASSWORDS (); @@ -709,26 +708,6 @@ createdb (UTIL_FUNCTION_ARG * arg) db_commit_transaction (); - { - /* FIXME!! Register Built-in Packages, The following lines should be moved */ - char built_in_package_spec[7][1024] = { - "CREATE OR REPLACE PROCEDURE enable (s INT) AS LANGUAGE JAVA NAME 'com.cubrid.plcsql.builtin.DBMS_OUTPUT.enable(int)';", - "CREATE OR REPLACE PROCEDURE disable () AS LANGUAGE JAVA NAME 'com.cubrid.plcsql.builtin.DBMS_OUTPUT.disable()';", - "CREATE OR REPLACE PROCEDURE put (str String) AS LANGUAGE JAVA NAME 'com.cubrid.plcsql.builtin.DBMS_OUTPUT.put(java.lang.String)';", - "CREATE OR REPLACE PROCEDURE put_line (str STRING) AS LANGUAGE JAVA NAME 'com.cubrid.plcsql.builtin.DBMS_OUTPUT.putLine(java.lang.String)';", - "CREATE OR REPLACE PROCEDURE new_line () AS LANGUAGE JAVA NAME 'com.cubrid.plcsql.builtin.DBMS_OUTPUT.newLine()';", - "CREATE OR REPLACE PROCEDURE get_line (line OUT STRING, status OUT INT) AS LANGUAGE JAVA NAME 'com.cubrid.plcsql.builtin.DBMS_OUTPUT.getLine(java.lang.String[], int[])';", - "CREATE OR REPLACE PROCEDURE get_lines (lines OUT STRING, cnt OUT INT) AS LANGUAGE JAVA NAME 'com.cubrid.plcsql.builtin.DBMS_OUTPUT.getLines(java.lang.String[], int[])';" - }; - - for (int i = 0; i < 7; i++) - { - execute_query (built_in_package_spec[i]); - } - - db_commit_transaction (); - } - if (user_define_file != NULL) { if (parse_user_define_file (user_define_file, output_file) != NO_ERROR) @@ -836,7 +815,6 @@ deletedb (UTIL_FUNCTION_ARG * arg) /* tuning system parameters */ sysprm_set_force (prm_get_name (PRM_ID_PB_NBUFFERS), "1024"); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); @@ -1065,8 +1043,6 @@ restoredb (UTIL_FUNCTION_ARG * arg) return EXIT_SUCCESS; } - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); db_login ("DBA", NULL); @@ -1151,7 +1127,6 @@ renamedb (UTIL_FUNCTION_ARG * arg) /* tuning system parameters */ sysprm_set_force (prm_get_name (PRM_ID_PB_NBUFFERS), "1024"); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); @@ -1264,8 +1239,6 @@ installdb (UTIL_FUNCTION_ARG * arg) cfg_added = true; - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); db_login ("DBA", NULL); @@ -1375,7 +1348,6 @@ copydb (UTIL_FUNCTION_ARG * arg) /* tuning system parameters */ sysprm_set_force (prm_get_name (PRM_ID_PB_NBUFFERS), "1024"); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); @@ -1458,8 +1430,6 @@ optimizedb (UTIL_FUNCTION_ARG * arg) snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", db_name, arg->command_name); er_init (er_msg_file, ER_NEVER_EXIT); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); db_login ("DBA", NULL); @@ -1608,8 +1578,6 @@ diagdb (UTIL_FUNCTION_ARG * arg) snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", db_name, arg->command_name); er_init (er_msg_file, ER_NEVER_EXIT); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); db_login ("DBA", NULL); @@ -2768,8 +2736,6 @@ synccolldb (UTIL_FUNCTION_ARG * arg) snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", db_name, arg->command_name); er_init (er_msg_file, ER_NEVER_EXIT); - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); db_login ("DBA", NULL); @@ -4751,8 +4717,6 @@ restoreslave (UTIL_FUNCTION_ARG * arg) return EXIT_SUCCESS; } - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - AU_DISABLE_PASSWORDS (); db_set_client_type (DB_CLIENT_TYPE_ADMIN_UTILITY); db_login ("DBA", NULL); diff --git a/src/executables/util_service.c b/src/executables/util_service.c index 270286b9e48..3511fa6f149 100644 --- a/src/executables/util_service.c +++ b/src/executables/util_service.c @@ -52,6 +52,7 @@ #include "release_string.h" #include "dynamic_array.h" #include "heartbeat.h" +#include "process_util.h" #include @@ -69,8 +70,8 @@ typedef enum UTIL_HELP = 6, UTIL_VERSION = 7, ADMIN = 8, - JAVASP_UTIL = 20, - GATEWAY = 21 + PL_UTIL = 20, // JAVASP_UTIL + GATEWAY = 21, } UTIL_SERVICE_INDEX_E; typedef enum @@ -119,10 +120,11 @@ typedef enum typedef enum { - JAVASP_SERVER_RUNNING = 0, - JAVASP_SERVER_STOPPED, - JAVASP_SERVER_STATUS_ERROR -} UTIL_JAVASP_SERVER_STATUS_E; + PL_SERVER_RUNNING = 0, + PL_SERVER_STOPPED, + PL_SERVER_STATUS_ERROR, + PL_SERVER_STARTING +} UTIL_PL_SERVER_STATUS_E; typedef struct { @@ -143,7 +145,7 @@ typedef struct #define UTIL_TYPE_MANAGER "manager" #define UTIL_TYPE_HEARTBEAT "heartbeat" #define UTIL_TYPE_HB_SHORT "hb" -#define UTIL_TYPE_JAVASP "javasp" +#define UTIL_TYPE_PL "pl" #define UTIL_TYPE_GATEWAY "gateway" static UTIL_SERVICE_OPTION_MAP_T us_Service_map[] = { @@ -153,7 +155,7 @@ static UTIL_SERVICE_OPTION_MAP_T us_Service_map[] = { {MANAGER, UTIL_TYPE_MANAGER, MASK_MANAGER}, {HEARTBEAT, UTIL_TYPE_HEARTBEAT, MASK_HEARTBEAT}, {HEARTBEAT, UTIL_TYPE_HB_SHORT, MASK_HEARTBEAT}, - {JAVASP_UTIL, UTIL_TYPE_JAVASP, MASK_JAVASP}, + {PL_UTIL, UTIL_TYPE_PL, MASK_PL}, {GATEWAY, UTIL_TYPE_GATEWAY, MASK_GATEWAY}, {UTIL_HELP, "--help", MASK_ALL}, {UTIL_VERSION, "--version", MASK_ALL}, @@ -223,7 +225,7 @@ static UTIL_SERVICE_OPTION_MAP_T us_Service_map[] = { static UTIL_SERVICE_OPTION_MAP_T us_Command_map[] = { {START, COMMAND_TYPE_START, MASK_ALL}, {STOP, COMMAND_TYPE_STOP, MASK_ALL}, - {RESTART, COMMAND_TYPE_RESTART, MASK_SERVICE | MASK_SERVER | MASK_BROKER | MASK_GATEWAY | MASK_JAVASP}, + {RESTART, COMMAND_TYPE_RESTART, MASK_SERVICE | MASK_SERVER | MASK_BROKER | MASK_GATEWAY | MASK_PL}, {STATUS, COMMAND_TYPE_STATUS, MASK_ALL}, {DEREGISTER, COMMAND_TYPE_DEREG, MASK_HEARTBEAT}, {LIST, COMMAND_TYPE_LIST, MASK_HEARTBEAT}, @@ -270,11 +272,10 @@ static int process_server (int command_type, int argc, char **argv, bool show_us static int process_broker (int command_type, int argc, const char **argv, bool process_window_service); static int process_gateway (int command_type, int argc, const char **argv, bool process_window_service); static int process_manager (int command_type, bool process_window_service); -static int process_javasp (int command_type, int argc, const char **argv, bool show_usage, bool suppress_message, - bool process_window_service, bool ha_mode); -static int process_javasp_start (const char *db_name, bool suppress_message, bool process_window_service); -static int process_javasp_stop (const char *db_name, bool suppress_message, bool process_window_service); -static int process_javasp_status (const char *db_name, bool suppress_message); +static int process_pl (int command_type, int argc, const char **argv, bool show_usage, bool suppress_message, + bool process_window_service, bool ha_mode); +static int process_pl_restart (const char *db_name, bool suppress_message, bool process_window_service); +static int process_pl_status (const char *db_name, bool suppress_message); static int process_heartbeat (int command_type, int argc, const char **argv); static int process_heartbeat_start (HA_CONF * ha_conf, int argc, const char **argv); static int process_heartbeat_stop (HA_CONF * ha_conf, int argc, const char **argv); @@ -294,15 +295,13 @@ static void hide_cmd_line_args (char **args); static int process_master (int command_type); static void print_message (FILE * output, int message_id, ...); static void print_result (const char *util_name, int status, int command_type); -static bool is_terminated_process (const int pid); static char *make_exec_abspath (char *buf, int buf_len, char *cmd); static const char *command_string (int command_type); static bool is_server_running (const char *type, const char *server_name, int pid); -static int shutdown_reviving_server (const char *server_name); static int is_broker_running (void); static int is_gateway_running (void); static UTIL_MANAGER_SERVER_STATUS_E is_manager_running (unsigned int sleep_time); -static UTIL_JAVASP_SERVER_STATUS_E is_javasp_running (const char *server_name); +static UTIL_PL_SERVER_STATUS_E is_pl_running (const char *server_name); static void get_server_names (const char *type, char **name_buffer); #if defined(WINDOWS) @@ -377,6 +376,9 @@ command_string (int command_type) case START: command = PRINT_CMD_START; break; + case RESTART: + command = PRINT_CMD_RESTART; + break; case STATUS: command = PRINT_CMD_STATUS; break; @@ -659,7 +661,7 @@ main (int argc, char *argv[]) { process_window_service = false; } - else if ((util_type == SERVER || util_type == BROKER || util_type == GATEWAY || util_type == JAVASP_UTIL) + else if ((util_type == SERVER || util_type == BROKER || util_type == GATEWAY || util_type == PL_UTIL) && (argc > 4) && strcmp ((char *) argv[4], "--for-windows-service") == 0) { process_window_service = false; @@ -692,9 +694,9 @@ main (int argc, char *argv[]) status = process_heartbeat (command_type, argc - 3, (const char **) &argv[3]); #endif /* !WINDOWs */ break; - case JAVASP_UTIL: + case PL_UTIL: // PL_UTIL status = - process_javasp (command_type, argc - 3, (const char **) &argv[3], true, false, process_window_service, false); + process_pl (command_type, argc - 3, (const char **) &argv[3], true, false, process_window_service, false); break; case GATEWAY: status = process_gateway (command_type, argc - 3, (const char **) &argv[3], process_window_service); @@ -1361,8 +1363,6 @@ process_service (int command_type, bool process_window_service) { if (!are_all_services_stopped (0, process_window_service)) { - (void) process_javasp (command_type, 0, NULL, false, false, process_window_service, false); - if (strcmp (get_property (SERVICE_START_SERVER), PROPERTY_ON) == 0 && us_Property_map[SERVER_START_LIST].property_value != NULL && us_Property_map[SERVER_START_LIST].property_value[0] != '\0') @@ -1418,7 +1418,7 @@ process_service (int command_type, bool process_window_service) const char *args[] = { "-b" }; (void) process_server (command_type, 0, NULL, false, true, false); - (void) process_javasp (command_type, 0, NULL, true, false, false, false); + (void) process_pl (command_type, 0, NULL, true, false, false, false); (void) process_broker (command_type, 1, args, false); (void) process_gateway (command_type, 1, args, false); (void) process_manager (command_type, false); @@ -1606,22 +1606,6 @@ is_server_running (const char *type, const char *server_name, int pid) } } -/* - * shutdown_reviving_server - - * - * return: - * - * type(in): - * server_name(in): - * pid(in): - */ -static int -shutdown_reviving_server (const char *server_name) -{ - const char *args[] = { UTIL_COMMDB_NAME, COMMDB_SHUTDOWN_REVIVING_SERVER, server_name, NULL }; - return proc_execute (UTIL_COMMDB_NAME, args, true, false, false, NULL); -} - /* * process_server - * @@ -1788,13 +1772,6 @@ process_server (int command_type, int argc, char **argv, bool show_usage, bool c status = ER_GENERIC_ERROR; } print_result (PRINT_SERVER_NAME, status, command_type); - - /* run javasp server if DB server is started successfully */ - if (status == NO_ERROR) - { - (void) process_javasp (command_type, 1, (const char **) &token, false, true, - process_window_service, false); - } } } } @@ -1808,13 +1785,6 @@ process_server (int command_type, int argc, char **argv, bool show_usage, bool c break; } - /* try to stop javasp server first */ - if (is_javasp_running (token) == JAVASP_SERVER_RUNNING) - { - (void) process_javasp (command_type, 1, (const char **) &token, false, true, process_window_service, - false); - } - print_message (stdout, MSGCAT_UTIL_GENERIC_START_STOP_3S, PRINT_SERVER_NAME, PRINT_CMD_STOP, token); if (is_server_running (CHECK_SERVER, token, 0)) @@ -1862,7 +1832,6 @@ process_server (int command_type, int argc, char **argv, bool show_usage, bool c status = ER_GENERIC_ERROR; print_message (stdout, MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_SERVER_NAME, token); util_log_write_errid (MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_SERVER_NAME, token); - shutdown_reviving_server (token); } } break; @@ -2795,14 +2764,14 @@ process_manager (int command_type, bool process_window_service) } /* - * is_javasp_running - + * is_pl_running - * * return: * */ -static UTIL_JAVASP_SERVER_STATUS_E -is_javasp_running (const char *server_name) +static UTIL_PL_SERVER_STATUS_E +is_pl_running (const char *server_name) { static const char PING_CMD[] = " ping "; static const int PING_CMD_LEN = sizeof (PING_CMD); @@ -2811,7 +2780,7 @@ is_javasp_running (const char *server_name) char buf[PATH_MAX] = { 0 }; char cmd[PATH_MAX] = { 0 }; - (void) envvar_bindir_file (cmd, PATH_MAX, UTIL_JAVASP_NAME); + (void) envvar_bindir_file (cmd, PATH_MAX, UTIL_PL_NAME); strcat (cmd, PING_CMD); strcat (cmd, server_name); @@ -2819,195 +2788,161 @@ is_javasp_running (const char *server_name) input = popen (cmd, "r"); if (input == NULL) { - return JAVASP_SERVER_STATUS_ERROR; + return PL_SERVER_STATUS_ERROR; } memset (buf, '\0', sizeof (buf)); if (fgets (buf, PATH_MAX, input) == NULL) { pclose (input); - return JAVASP_SERVER_STATUS_ERROR; + return PL_SERVER_STATUS_ERROR; } if (strcmp (buf, server_name) == 0) { pclose (input); - return JAVASP_SERVER_RUNNING; + return PL_SERVER_RUNNING; + } + else if (strcmp (buf, "NO_PROCESS") == 0) + { + pclose (input); + return PL_SERVER_STOPPED; } else if (strcmp (buf, "NO_CONNECTION") == 0) { pclose (input); - return JAVASP_SERVER_STOPPED; + return PL_SERVER_STARTING; } else { pclose (input); - return JAVASP_SERVER_STATUS_ERROR; + return PL_SERVER_STATUS_ERROR; } } static int -process_javasp_start (const char *db_name, bool suppress_message, bool process_window_service) +process_pl_restart (const char *db_name, bool suppress_message, bool process_window_service) { - static const int wait_timeout = 30; + int status = NO_ERROR; + static const int wait_timeout = 10; int waited_secs = 0; - int pid = 0; - int status = ER_GENERIC_ERROR; if (!suppress_message) { - print_message (stdout, MSGCAT_UTIL_GENERIC_START_STOP_3S, PRINT_JAVASP_NAME, PRINT_CMD_START, db_name); + print_message (stdout, MSGCAT_UTIL_GENERIC_START_STOP_3S, PRINT_PL_NAME, PRINT_CMD_RESTART, db_name); } - UTIL_JAVASP_SERVER_STATUS_E javasp_status = is_javasp_running (db_name); - if (javasp_status == JAVASP_SERVER_RUNNING) + if (!is_server_running (CHECK_SERVER, db_name, 0)) { + status = ER_GENERIC_ERROR; if (!suppress_message) { - print_message (stdout, MSGCAT_UTIL_GENERIC_ALREADY_RUNNING_2S, PRINT_JAVASP_NAME, db_name); + print_message (stdout, MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_SERVER_NAME, db_name); } - util_log_write_errid (MSGCAT_UTIL_GENERIC_ALREADY_RUNNING_2S, PRINT_JAVASP_NAME, db_name); } - else + + if (status == NO_ERROR) { if (process_window_service) { #if defined(WINDOWS) - const char *args[] = { UTIL_WIN_SERVICE_CONTROLLER_NAME, PRINT_CMD_JAVASP, - COMMAND_TYPE_START, db_name, NULL + const char *args[] = { UTIL_WIN_SERVICE_CONTROLLER_NAME, PRINT_CMD_PL, + COMMAND_TYPE_STOP, db_name, NULL }; + status = proc_execute (UTIL_WIN_SERVICE_CONTROLLER_NAME, args, true, false, false, NULL); #endif } else { - const char *args[] = { UTIL_JAVASP_NAME, db_name, NULL }; - status = proc_execute (UTIL_JAVASP_NAME, args, false, false, false, &pid); + const char *args[] = { UTIL_PL_NAME, COMMAND_TYPE_STOP, db_name, NULL }; + status = proc_execute (UTIL_PL_NAME, args, true, false, false, NULL); + sleep (1); } - status = ER_GENERIC_ERROR; - while (status != NO_ERROR && waited_secs < wait_timeout) + UTIL_PL_SERVER_STATUS_E pl_status; + do { - if (pid != 0 && is_terminated_process (pid)) - { - break; - } + // The pl server needs a few seconds to accept ping request + pl_status = is_pl_running (db_name); + status = (pl_status == PL_SERVER_RUNNING) ? NO_ERROR : ER_GENERIC_ERROR; + sleep (1); // wait to stop - javasp_status = is_javasp_running (db_name); - if (javasp_status == JAVASP_SERVER_RUNNING) + if (!is_server_running (CHECK_SERVER, db_name, 0)) { - status = NO_ERROR; - break; - } - else - { - sleep (1); /* wait to start */ - waited_secs++; - - if (javasp_status == JAVASP_SERVER_STOPPED) - { - util_log_write_errstr ("Waiting for javasp server to start... (%d / %d)\n", waited_secs, - wait_timeout); - } - else + status = ER_GENERIC_ERROR; + if (!suppress_message) { - if (waited_secs > 3) - { - /* invalid database name or failed to open info file, wait upto 3 seconds */ - break; - } + print_message (stdout, MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_SERVER_NAME, db_name); } + break; } + + waited_secs++; } - if (!suppress_message) - { - print_result (PRINT_JAVASP_NAME, status, START); - } - else - { - fprintf (stdout, "Calling java stored procedure %s allowed\n", (status == NO_ERROR) ? "is" : "is not"); - } + while (status != NO_ERROR && waited_secs < wait_timeout); + } + + if (!suppress_message) + { + print_result (PRINT_PL_NAME, status, RESTART); } + return status; } static int -process_javasp_stop (const char *db_name, bool suppress_message, bool process_window_service) +process_pl_status (const char *db_name) { int status = NO_ERROR; - static const int wait_timeout = 5; + + static const int wait_timeout = 10; int waited_secs = 0; + UTIL_PL_SERVER_STATUS_E pl_status; - if (!suppress_message) - { - print_message (stdout, MSGCAT_UTIL_GENERIC_START_STOP_3S, PRINT_JAVASP_NAME, PRINT_CMD_STOP, db_name); - } - UTIL_JAVASP_SERVER_STATUS_E javasp_status = is_javasp_running (db_name); - if (javasp_status == JAVASP_SERVER_RUNNING) + do { - if (process_window_service) + if (!is_server_running (CHECK_SERVER, db_name, 0)) { -#if defined(WINDOWS) - const char *args[] = { UTIL_WIN_SERVICE_CONTROLLER_NAME, PRINT_CMD_JAVASP, - COMMAND_TYPE_STOP, db_name, NULL - }; - - status = proc_execute (UTIL_WIN_SERVICE_CONTROLLER_NAME, args, true, false, false, NULL); -#endif + status = ER_GENERIC_ERROR; + print_message (stdout, MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_SERVER_NAME, db_name); + return status; } - else + + + pl_status = is_pl_running (db_name); + if (pl_status == PL_SERVER_RUNNING) { - const char *args[] = { UTIL_JAVASP_NAME, COMMAND_TYPE_STOP, db_name, NULL }; - status = proc_execute (UTIL_JAVASP_NAME, args, true, false, false, NULL); - do + const char *args[] = { UTIL_PL_NAME, COMMAND_TYPE_STATUS, db_name, NULL }; + status = proc_execute (UTIL_PL_NAME, args, true, false, false, NULL); + if (status == NO_ERROR) { - status = (is_javasp_running (db_name) == JAVASP_SERVER_RUNNING) ? ER_GENERIC_ERROR : NO_ERROR; - sleep (1); /* wait to stop */ - waited_secs++; + break; } - while (status != NO_ERROR && waited_secs < wait_timeout); - } - if (!suppress_message) - { - print_result (PRINT_JAVASP_NAME, status, STOP); } - } - else - { - status = ER_GENERIC_ERROR; - if (!suppress_message) + else { - print_message (stdout, MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_JAVASP_NAME, db_name); + status = ER_GENERIC_ERROR; } - util_log_write_errid (MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_JAVASP_NAME, db_name); - } - return status; -} - -static int -process_javasp_status (const char *db_name) -{ - int status = NO_ERROR; - UTIL_JAVASP_SERVER_STATUS_E javasp_status = is_javasp_running (db_name); - if (javasp_status == JAVASP_SERVER_RUNNING) - { - const char *args[] = { UTIL_JAVASP_NAME, COMMAND_TYPE_STATUS, db_name, NULL }; - status = proc_execute (UTIL_JAVASP_NAME, args, true, false, false, NULL); + // retry + sleep (1); + waited_secs++; } - else + while (status != NO_ERROR && waited_secs < wait_timeout); + + if (status != NO_ERROR) { - status = ER_GENERIC_ERROR; - print_message (stdout, MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_JAVASP_NAME, db_name); - util_log_write_errid (MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_JAVASP_NAME, db_name); + print_message (stdout, MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_PL_NAME, db_name); + util_log_write_errid (MSGCAT_UTIL_GENERIC_NOT_RUNNING_2S, PRINT_PL_NAME, db_name); } return status; } static int -process_javasp (int command_type, int argc, const char **argv, bool show_usage, bool suppress_message, - bool process_window_service, bool ha_mode) +process_pl (int command_type, int argc, const char **argv, bool show_usage, bool suppress_message, + bool process_window_service, bool ha_mode) { const int buf_size = 4096; char *buf = NULL; @@ -3027,7 +2962,7 @@ process_javasp (int command_type, int argc, const char **argv, bool show_usage, get_server_names (server_type, &buf); } } - else /* cubrid javasp command */ + else /* cubrid pl command */ { buf = (char *) calloc (sizeof (char), buf_size); strncpy (buf, argv[0], buf_size); @@ -3037,7 +2972,7 @@ process_javasp (int command_type, int argc, const char **argv, bool show_usage, { if (show_usage) { - util_service_usage (JAVASP_UTIL); + util_service_usage (PL_UTIL); util_log_write_errid (MSGCAT_UTIL_GENERIC_INVALID_CMD); } status = ER_GENERIC_ERROR; @@ -3046,7 +2981,7 @@ process_javasp (int command_type, int argc, const char **argv, bool show_usage, if (command_type == STATUS && !suppress_message) { - print_message (stdout, MSGCAT_UTIL_GENERIC_START_STOP_2S, PRINT_JAVASP_NAME, PRINT_CMD_STATUS); + print_message (stdout, MSGCAT_UTIL_GENERIC_START_STOP_2S, PRINT_PL_NAME, PRINT_CMD_STATUS); } list = buf; @@ -3060,17 +2995,22 @@ process_javasp (int command_type, int argc, const char **argv, bool show_usage, switch (command_type) { case START: - status = process_javasp_start (db_name, suppress_message, process_window_service); + if (!suppress_message) + { + print_message (stderr, MSGCAT_UTIL_GENERIC_SERVICE_INVALID_CMD, PRINT_CMD_START); + } break; case STOP: - status = process_javasp_stop (db_name, suppress_message, process_window_service); + if (!suppress_message) + { + print_message (stderr, MSGCAT_UTIL_GENERIC_SERVICE_INVALID_CMD, PRINT_CMD_STOP); + } break; case RESTART: - status = process_javasp_stop (db_name, suppress_message, process_window_service); - status = process_javasp_start (db_name, suppress_message, process_window_service); + status = process_pl_restart (db_name, suppress_message, process_window_service); break; case STATUS: - status = process_javasp_status (db_name); + status = process_pl_status (db_name); break; default: status = ER_GENERIC_ERROR; @@ -4001,9 +3941,6 @@ us_hb_deactivate (const char *hostname, bool immediate_stop) args[opt_idx++] = COMMDB_HB_DEACT_IMMEDIATELY; } - /* stop javasp server */ - (void) process_javasp (STOP, 0, NULL, false, true, false, true); - /* stop all HA processes including cub_server */ args[opt_idx] = COMMDB_HA_DEACT_STOP_ALL; status = proc_execute (UTIL_COMMDB_NAME, args, true, false, false, NULL); @@ -4052,9 +3989,6 @@ us_hb_process_stop (HA_CONF * ha_conf, const char *db_name) print_message (stdout, MSGCAT_UTIL_GENERIC_START_STOP_2S, PRINT_HA_PROCS_NAME, PRINT_CMD_STOP); - /* stop javasp server */ - (void) process_javasp (STOP, 1, (const char **) &db_name, false, true, false, true); - status = us_hb_copylogdb_stop (ha_conf, db_name, NULL, NULL); if (status != NO_ERROR) { @@ -5216,7 +5150,7 @@ load_properties (void) bool gateway_flag = false; bool manager_flag = false; bool heartbeat_flag = false; - bool javasp_flag = false; + bool pl_flag = false; char *value = NULL; @@ -5327,36 +5261,3 @@ get_property (int property_type) { return us_Property_map[property_type].property_value; } - -/* - * is_terminated_process() - test if the process is terminated - * return: true if the process is terminated, otherwise false - * pid(in): process id - */ -static bool -is_terminated_process (const int pid) -{ -#if defined(WINDOWS) - HANDLE h_process; - - h_process = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid); - if (h_process == NULL) - { - return true; - } - else - { - CloseHandle (h_process); - return false; - } -#else /* WINDOWS */ - if (kill (pid, 0) == -1) - { - return true; - } - else - { - return false; - } -#endif /* WINDOWS */ -} diff --git a/src/executables/utility.h b/src/executables/utility.h index c1630f4c299..56818334016 100644 --- a/src/executables/utility.h +++ b/src/executables/utility.h @@ -126,7 +126,7 @@ typedef enum MSGCAT_UTIL_GENERIC_MANAGER_NOT_INSTALLED = 41, MSGCAT_UTIL_GENERIC_INVALID_ARGUMENT = 42, MSGCAT_UTIL_GENERIC_FILEOPEN_ERROR = 43, - /* javasp usage = 44 ? */ + /* pl usage = 44 ? */ /* gateway usage = 45 ? */ MSGCAT_UTIL_GENERIC_CLASSNAME_EXCEED_MAX_LENGTH = 46, MSGCAT_UTIL_GENERIC_CLASSNAME_INVALID_FORMAT = 47, @@ -894,7 +894,7 @@ typedef struct _ha_config #define UTIL_CUBRID "cubrid" UTIL_EXE_EXT #define UTIL_COPYLOGDB "copylogdb" UTIL_EXE_EXT #define UTIL_APPLYLOGDB "applylogdb" UTIL_EXE_EXT -#define UTIL_JAVASP_NAME "cub_javasp" UTIL_EXE_EXT +#define UTIL_PL_NAME "cub_pl" UTIL_EXE_EXT #define UTIL_PLCSQL_HELPER_NAME "plcsql_helper" UTIL_EXE_EXT #define PROPERTY_ON "on" @@ -908,7 +908,7 @@ typedef struct _ha_config #define PRINT_GATEWAY_NAME "cubrid gateway" #define PRINT_MANAGER_NAME "cubrid manager server" #define PRINT_HEARTBEAT_NAME "cubrid heartbeat" -#define PRINT_JAVASP_NAME "cubrid javasp" +#define PRINT_PL_NAME "cubrid pl" #define PRINT_HA_PROCS_NAME "HA processes" #define PRINT_CMD_SERVICE "service" @@ -916,9 +916,10 @@ typedef struct _ha_config #define PRINT_CMD_GATEWAY "gateway" #define PRINT_CMD_MANAGER "manager" #define PRINT_CMD_SERVER "server" -#define PRINT_CMD_JAVASP "javasp" +#define PRINT_CMD_PL "pl" #define PRINT_CMD_START "start" +#define PRINT_CMD_RESTART "restart" #define PRINT_CMD_STOP "stop" #define PRINT_CMD_STATUS "status" #define PRINT_CMD_DEREG "deregister" @@ -959,7 +960,6 @@ typedef struct _ha_config #define COMMDB_HA_ADMIN_INFO "--admin-info" #define COMMDB_VERBOSE_OUTPUT "--verbose" #define COMMDB_HA_START_UTIL_PROCESS "-t" -#define COMMDB_SHUTDOWN_REVIVING_SERVER "--shutdown-reviving-server" #define ACLDB_RELOAD "-r" @@ -971,7 +971,7 @@ typedef struct _ha_config #define MASK_GATEWAY 0x10 #define MASK_ADMIN 0x20 #define MASK_HEARTBEAT 0x40 -#define MASK_JAVASP 0x80 +#define MASK_PL 0x80 /* utility option list */ #define UTIL_OPTION_CREATEDB "createdb" @@ -1532,8 +1532,6 @@ typedef struct _ha_config #define COMMDB_HA_ADMIN_INFO_L "admin-info" #define COMMDB_HA_START_UTIL_PROCESS_S 't' #define COMMDB_HA_START_UTIL_PROCESS_L "start-ha-util-process" -#define COMMDB_SHUTDOWN_REVIVING_SERVER_S 12116 -#define COMMDB_SHUTDOWN_REVIVING_SERVER_L "shutdown-reviving-server" /* paramdump option list */ #define PARAMDUMP_OUTPUT_FILE_S 'o' diff --git a/src/loaddb/load_db.c b/src/loaddb/load_db.c index 90c8fcbd08e..8c4e10c4f53 100644 --- a/src/loaddb/load_db.c +++ b/src/loaddb/load_db.c @@ -564,8 +564,6 @@ loaddb_internal (UTIL_FUNCTION_ARG * arg, int dba_mode) sysprm_set_force (prm_get_name (PRM_ID_SR_NBUFFERS), LOAD_INDEX_MIN_SORT_BUFFER_PAGES_STRING); } - sysprm_set_force (prm_get_name (PRM_ID_JAVA_STORED_PROCEDURE), "no"); - /* open loaddb log file */ sprintf (log_file_name, "%s_%s", args.volume.c_str (), LOADDB_LOG_FILENAME_SUFFIX); loaddb_log_file = fopen (log_file_name, "w+"); diff --git a/src/loaddb/load_sa_loader.cpp b/src/loaddb/load_sa_loader.cpp index 46ad642b464..a18a0fe93ca 100644 --- a/src/loaddb/load_sa_loader.cpp +++ b/src/loaddb/load_sa_loader.cpp @@ -72,6 +72,7 @@ #include "utility.h" #include "work_space.h" #include "schema_system_catalog_constants.h" +#include "pl_sr.h" using namespace cubload; @@ -6369,6 +6370,8 @@ ldr_sa_load (load_args *args, int *status, bool *interrupted) locator_Dont_check_foreign_key = true; ldr_init (args); + pl_server_init (args->volume.c_str ()); + /* set the flag to indicate what type of interrupts to raise If logging has been disabled set commit flag. If * logging is enabled set abort flag. */ @@ -6541,6 +6544,8 @@ ldr_sa_load (load_args *args, int *status, bool *interrupted) ldr_final (); + pl_server_destroy (); + if (ldr_Driver != NULL) { delete ldr_Driver; diff --git a/src/method/method_callback.cpp b/src/method/method_callback.cpp index c5dac8a9d03..58e4cc965ab 100644 --- a/src/method/method_callback.cpp +++ b/src/method/method_callback.cpp @@ -19,12 +19,9 @@ #include "method_callback.hpp" #include "dbi.h" -#include "api_compat.h" - #include "ddl_log.h" -#include "method_def.hpp" -#include "method_compile.hpp" +#include "pl_struct_compile.hpp" #include "method_query_util.hpp" #include "method_struct_oid_info.hpp" #include "method_schema_info.hpp" @@ -44,10 +41,13 @@ #include "transform.h" #include "execute_statement.h" #include "schema_manager.h" +#include "network_callback_cl.hpp" extern int ux_create_srv_handle_with_method_query_result (DB_QUERY_RESULT *result, int stmt_type, int num_column, DB_QUERY_TYPE *column_info, bool is_holdable); +using namespace cubpl; + namespace cubmethod { callback_handler::callback_handler (int max_query_handler) @@ -116,6 +116,9 @@ namespace cubmethod case METHOD_CALLBACK_GET_GLOBAL_SEMANTICS: error = get_global_semantics (unpacker); break; + case METHOD_CALLBACK_CHANGE_RIGHTS: + error = change_rights (unpacker); + break; default: assert (false); error = ER_FAILED; @@ -123,7 +126,7 @@ namespace cubmethod } #if defined (CS_MODE) - mcon_send_queue_data_to_server (); + xs_queue_send (); #else /* do nothing for SA_MODE */ #endif @@ -134,34 +137,37 @@ namespace cubmethod int callback_handler::end_transaction (packing_unpacker &unpacker) { + int error_code = NO_ERROR; int command; // commit : 1, abort : 2 unpacker.unpack_all (command); if (command == 1) { - db_commit_transaction (); + error_code = db_commit_transaction (); } else if (command == 2) { - db_abort_transaction (); + error_code = db_abort_transaction (); } else { assert (false); + error_code = ER_FAILED; } - free_query_handle_all (true); + if (error_code != NO_ERROR) + { + m_error_ctx.set_error (db_error_code (), db_error_string (1), __FILE__, __LINE__); + } if (m_error_ctx.has_error()) { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, 1); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, 1); } - - return NO_ERROR; } int @@ -169,16 +175,16 @@ namespace cubmethod { std::string sql; int flag; - unpacker.unpack_all (sql, flag); + TRANID tid; + unpacker.unpack_all (sql, flag, tid); /* find in m_sql_handler_map */ - query_handler *handler = get_query_handler_by_sql (sql); - if (handler != nullptr) - { - /* found in statement handler cache */ - handler->set_is_occupied (true); - } - else + query_handler *handler = get_query_handler_by_sql (sql, [&] (query_handler *h) + { + return h->get_is_occupied() == false && (h->get_tran_id () == NULL_TRANID || h->get_tran_id() == tid); + }); + + if (handler == nullptr) { /* not found in statement handler cache */ handler = new_query_handler (); @@ -194,6 +200,7 @@ namespace cubmethod { // add to statement handler cache m_sql_handler_map.emplace (sql, handler->get_id ()); + handler->set_tran_id (tid); } else { @@ -202,9 +209,11 @@ namespace cubmethod } } - /* DDL audit */ - if (handler) + if (handler != nullptr) { + handler->set_is_occupied (true); + + /* DDL audit */ DB_SESSION *hdl_session = handler->get_db_session(); logddl_set_callback_stmt (handler->get_statement_type(), (char *) sql.c_str (), sql.size (), m_error_ctx.get_error (), ((hdl_session && hdl_session->parser) ? & (hdl_session->parser->hide_pwd_info) : NULL)); @@ -212,11 +221,11 @@ namespace cubmethod if (m_error_ctx.has_error()) { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, handler->get_prepare_info ()); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, handler->get_prepare_info ()); } } @@ -268,11 +277,11 @@ namespace cubmethod if (m_error_ctx.has_error()) { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, handler->get_execute_info ()); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, handler->get_execute_info ()); } } @@ -290,12 +299,12 @@ namespace cubmethod make_outresult_info info; query_handler->set_prepare_column_list_info (info.column_infos); query_handler->set_qresult_info (info.qresult_info); - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, info); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, info); } /* unexpected error, should not be here */ m_error_ctx.set_error (METHOD_CALLBACK_ER_INTERNAL, NULL, __FILE__, __LINE__); - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); } int @@ -315,11 +324,11 @@ namespace cubmethod get_generated_keys_info info = handler->generated_keys (); if (m_error_ctx.has_error()) { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, info); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, info); } } @@ -354,11 +363,11 @@ namespace cubmethod oid_get_info info = get_oid_handler()->oid_get (request.oid, request.attr_names); if (m_error_ctx.has_error()) { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, info); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, info); } } @@ -371,11 +380,11 @@ namespace cubmethod int result = get_oid_handler()->oid_put (request.oid, request.attr_names, request.db_values); if (m_error_ctx.has_error()) { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, result); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, result); } } @@ -393,11 +402,11 @@ namespace cubmethod int res_code = get_oid_handler()->oid_cmd (oid, cmd, res); if (m_error_ctx.has_error()) { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, res_code, res); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, res_code, res); } } @@ -417,11 +426,11 @@ namespace cubmethod if (m_error_ctx.has_error()) { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, m_error_ctx); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, result); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, result); } } @@ -579,11 +588,11 @@ namespace cubmethod if (error == NO_ERROR) { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, response); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, response); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, response); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, response); } } @@ -599,7 +608,8 @@ namespace cubmethod AU_DISABLE (save); { - mop_p = jsp_find_stored_procedure (name); + // TODO + mop_p = jsp_find_stored_procedure (name, DB_AUTH_NONE); if (mop_p == NULL) { assert (er_errid () != NO_ERROR); @@ -864,11 +874,48 @@ namespace cubmethod if (error == NO_ERROR) { - return mcon_pack_and_queue (METHOD_RESPONSE_SUCCESS, response); + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, response); } else { - return mcon_pack_and_queue (METHOD_RESPONSE_ERROR, response); + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, response); + } + } + + int + callback_handler::change_rights (packing_unpacker &unpacker) + { + int error = NO_ERROR; + + int command; + std::string auth_user_name; + unpacker.unpack_int (command); + + if (command == 0) // PUSH + { + unpacker.unpack_string (auth_user_name); + MOP user = au_find_user (auth_user_name.c_str ()); + if (user == NULL) + { + error = ER_FAILED; + } + else + { + au_perform_push_user (user); + } + } + else // POP + { + au_perform_pop_user (); + } + + if (error == NO_ERROR) + { + return xs_pack_and_queue (METHOD_RESPONSE_SUCCESS, 1); + } + else + { + return xs_pack_and_queue (METHOD_RESPONSE_ERROR, 0); } } @@ -939,7 +986,7 @@ namespace cubmethod // clear handler ID> m_sql_handler_map.erase (m_query_handlers[id]->get_sql_stmt()); - delete m_query_handlers[id]; + m_deferred_query_free_handler.push_back (m_query_handlers[id]); m_query_handlers[id] = nullptr; } else @@ -958,6 +1005,16 @@ namespace cubmethod } } + void + callback_handler::free_deferred_query_handler () + { + for (auto it = m_deferred_query_free_handler.begin(); it != m_deferred_query_free_handler.end(); it++) + { + delete *it; + } + m_deferred_query_free_handler.clear(); + } + query_handler * callback_handler::get_query_handler_by_query_id (const uint64_t qid) { @@ -973,12 +1030,12 @@ namespace cubmethod } query_handler * - callback_handler::get_query_handler_by_sql (const std::string &sql) + callback_handler::get_query_handler_by_sql (const std::string &sql, std::function cond) { for (auto it = m_sql_handler_map.lower_bound (sql); it != m_sql_handler_map.upper_bound (sql); it++) { query_handler *handler = get_query_handler_by_id (it->second); - if (handler != nullptr && handler->get_is_occupied() == false) + if (handler != nullptr && cond (handler)) { /* found */ return handler; @@ -988,12 +1045,19 @@ namespace cubmethod return nullptr; } + std::queue & + callback_handler::get_data_queue () + { + return m_data_queue; + } + ////////////////////////////////////////////////////////////////////////// // Global method callback handler interface ////////////////////////////////////////////////////////////////////////// static callback_handler handler (100); - callback_handler *get_callback_handler (void) + callback_handler * + get_callback_handler (void) { return &handler; } diff --git a/src/method/method_callback.hpp b/src/method/method_callback.hpp index c54ceca10e5..669dd6532bf 100644 --- a/src/method/method_callback.hpp +++ b/src/method/method_callback.hpp @@ -29,9 +29,8 @@ #include #include +#include -#include "method_connection_cl.hpp" -#include "method_def.hpp" #include "method_error.hpp" #include "method_oid_handler.hpp" #include "method_query_handler.hpp" @@ -73,14 +72,18 @@ namespace cubmethod void free_query_handle (int id, bool is_free); void free_query_handle_all (bool is_free); + void free_deferred_query_handler (); /* find query handler */ query_handler *get_query_handler_by_id (const int id); query_handler *get_query_handler_by_query_id (const uint64_t qid); /* used for out resultset */ - query_handler *get_query_handler_by_sql (const std::string &sql); /* used for statement handler cache */ + query_handler *get_query_handler_by_sql (const std::string &sql, + std::function cond); /* used for statement handler cache */ oid_handler *get_oid_handler (); + std::queue &get_data_queue (); + private: /* handle related to query */ int end_transaction (packing_unpacker &unpacker); @@ -102,6 +105,9 @@ namespace cubmethod int get_sql_semantics (packing_unpacker &unpacker); int get_global_semantics (packing_unpacker &unpacker); + /* handle auth */ + int change_rights (packing_unpacker &unpacker); + /* ported from cas_handle */ query_handler *new_query_handler (); @@ -112,6 +118,10 @@ namespace cubmethod std::vector m_query_handlers; oid_handler *m_oid_handler; + + std::queue m_data_queue; + + std::list m_deferred_query_free_handler; }; ////////////////////////////////////////////////////////////////////////// diff --git a/src/method/method_compile.cpp b/src/method/method_compile.cpp deleted file mode 100644 index 1b8e5ad8298..00000000000 --- a/src/method/method_compile.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "method_compile.hpp" - -#include "jsp_comm.h" -#include "method_runtime_context.hpp" -#include "method_connection_sr.hpp" -#include "method_connection_java.hpp" -#include "method_compile_def.hpp" -// XXX: SHOULD BE THE LAST INCLUDE HEADER -#include "memory_wrapper.hpp" - -namespace cubmethod -{ -#if defined (SERVER_MODE) || defined (SA_MODE) - int callback_send_and_receive (cubthread::entry &thread_ref, runtime_context &ctx, - const SOCKET java_socket, cubpacking::packable_object &obj) - { - int error = NO_ERROR; - - SESSION_ID s_id = thread_ref.conn_entry->session_id; - header header (s_id, METHOD_REQUEST_CALLBACK, ctx.get_and_increment_request_id ()); - error = method_send_data_to_client (&thread_ref, header, obj); - if (error != NO_ERROR) - { - return error; - } - - auto reponse_lambda = [&] (cubmem::block & b) - { - header.req_id = ctx.get_and_increment_request_id (); - return mcon_send_data_to_java (java_socket, header, b); - }; - - error = xs_receive (&thread_ref, reponse_lambda); - return error; - } - - int invoke_compile (cubthread::entry &thread_ref, runtime_context &ctx, const std::string &program, - const bool &verbose, cubmem::extensible_block &out_blk) - { - int error = NO_ERROR; - connection *conn = ctx.get_connection_pool().claim(); - SESSION_ID s_id = thread_ref.conn_entry->session_id; - header header (s_id, SP_CODE_COMPILE, ctx.get_and_increment_request_id ()); - SOCKET socket = conn->get_socket (); - { - error = mcon_send_data_to_java (socket, header, verbose, program); - if (error != NO_ERROR) - { - goto exit; - } - - int code; - do - { - cubmem::block response_blk; - error = cubmethod::mcon_read_data_from_java (socket, response_blk); - if (error != NO_ERROR || response_blk.dim == 0) - { - error = ER_FAILED; - goto exit; - } - - packing_unpacker unpacker (response_blk); - unpacker.unpack_int (code); - - char *aligned_ptr = PTR_ALIGN (unpacker.get_curr_ptr(), MAX_ALIGNMENT); - cubmem::block payload_blk ((size_t) (unpacker.get_buffer_end() - aligned_ptr), - aligned_ptr); - - switch (code) - { - case METHOD_REQUEST_COMPILE: - { - out_blk.extend_to (payload_blk.dim); - std::memcpy (out_blk.get_ptr (), payload_blk.ptr, payload_blk.dim); - error = NO_ERROR; - break; - } - - case METHOD_REQUEST_SQL_SEMANTICS: - { - packing_unpacker respone_unpacker (payload_blk); - sql_semantics_request request; - respone_unpacker.unpack_all (request); - error = callback_send_and_receive (thread_ref, ctx, socket, request); - break; - } - - case METHOD_REQUEST_GLOBAL_SEMANTICS: - { - packing_unpacker respone_unpacker (payload_blk); - global_semantics_request request; - respone_unpacker.unpack_all (request); - error = callback_send_and_receive (thread_ref, ctx, socket, request); - break; - } - } - - // free phase - if (response_blk.dim > 0) - { - free (response_blk.ptr); - } - - if (error != NO_ERROR) - { - break; - } - } - while (code != METHOD_REQUEST_COMPILE); - -exit: - ctx.get_connection_pool().retire (conn, true); - - return error; - } - } -#endif -} diff --git a/src/method/method_connection.hpp b/src/method/method_connection.hpp deleted file mode 100644 index 0ba027d0b2a..00000000000 --- a/src/method/method_connection.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * method_connection.hpp - */ - -#ifndef _METHOD_CONNECTION_HPP_ -#define _METHOD_CONNECTION_HPP_ - -#include - -#include "porting.h" - -#include "mem_block.hpp" /* cubmem::block */ -#include "packer.hpp" /* packing_packer */ - -// thread_entry.hpp -namespace cubthread -{ - class entry; -} - -namespace cubmethod -{ - template - cubmem::extensible_block mcon_pack_data (Args &&... args) - { - packing_packer packer; - cubmem::extensible_block eb; - packer.set_buffer_and_pack_all (eb, std::forward (args)...); - return eb; - } - - template - cubmem::block mcon_pack_data_block (Args &&... args) - { - packing_packer packer; - cubmem::extensible_block eb; - packer.set_buffer_and_pack_all (eb, std::forward (args)...); - cubmem::block b (packer.get_current_size(), eb.release_ptr()); - return b; - } -} - -#endif // _METHOD_CONNECTION_HPP_ diff --git a/src/method/method_connection_cl.cpp b/src/method/method_connection_cl.cpp deleted file mode 100644 index 26f825d6797..00000000000 --- a/src/method/method_connection_cl.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "method_connection_cl.hpp" - - -namespace cubmethod -{ - static std::queue s_data_queue; - - std::queue &mcon_get_data_queue () - { - return s_data_queue; - } - -#if defined (CS_MODE) - static method_server_conn_info s_conn_info [METHOD_MAX_RECURSION_DEPTH + 1]; - - void mcon_set_connection_info (int idx, int rc) - { - method_server_conn_info &info = s_conn_info [idx]; - info.rc = rc; - } - - method_server_conn_info *get_connection_info (int idx) - { - if (idx <= METHOD_MAX_RECURSION_DEPTH) - { - return &s_conn_info[idx]; - } - else - { - return nullptr; - } - } - - int - mcon_send_queue_data_to_server () - { - int depth = tran_get_libcas_depth () - 1; - method_server_conn_info *info = get_connection_info (depth); - - assert (info); - assert (!mcon_get_data_queue().empty()); - - cubmem::extensible_block &blk = mcon_get_data_queue().front (); - int error = net_client_send_data (net_client_get_server_host(), info->rc, blk.get_ptr (), blk.get_size()); - mcon_get_data_queue().pop (); - return error; - } - -#endif - -} // cubmethod diff --git a/src/method/method_connection_cl.hpp b/src/method/method_connection_cl.hpp deleted file mode 100644 index 5f936d6be5a..00000000000 --- a/src/method/method_connection_cl.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * method_connection_cl.hpp - */ - -#ifndef _METHOD_CONNECTION_CL_HPP_ -#define _METHOD_CONNECTION_CL_HPP_ - -#if defined (SERVER_MODE) -#error does not belong to server -#endif // SERVER_MODE - -#include - -#include "network_interface_cl.h" -#include "method_def.hpp" -#include "mem_block.hpp" -#include "packer.hpp" -#include "transaction_cl.h" - -struct method_server_conn_info -{ - unsigned int rc; -}; - -namespace cubmethod -{ - ////////////////////////////////////////////////////////////////////////// - // Data Queue - ////////////////////////////////////////////////////////////////////////// - - std::queue &mcon_get_data_queue (); - - template - int mcon_pack_and_queue (Args &&... args) - { - packing_packer packer; - cubmem::extensible_block eb; - packer.set_buffer_and_pack_all (eb, std::forward (args)...); - eb.extend_to (packer.get_current_size ()); // ensure eb.get_size () == packer.get_current_size () - - mcon_get_data_queue().push (std::move (eb)); - return NO_ERROR; - } - -#if defined (CS_MODE) - ////////////////////////////////////////////////////////////////////////// - // Interface to communicate with DB Server - ////////////////////////////////////////////////////////////////////////// - - void mcon_set_connection_info (int idx, int rc); - method_server_conn_info *get_connection_info (int idx); - int mcon_send_queue_data_to_server (); - - template - int mcon_send_data_to_server (Args &&... args) - { - mcon_pack_and_queue (std::forward (args)...); - mcon_send_queue_data_to_server (); - return NO_ERROR; - } -#else - template - int mcon_send_data_to_server (Args &&... args) - { - mcon_pack_and_queue (std::forward (args)...); - return NO_ERROR; - } -#endif -} // cubmethod - -#endif // _METHOD_CONNECTION_CL_HPP_ diff --git a/src/method/method_connection_java.cpp b/src/method/method_connection_java.cpp deleted file mode 100644 index 10684a41a48..00000000000 --- a/src/method/method_connection_java.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "method_connection_java.hpp" -// XXX: SHOULD BE THE LAST INCLUDE HEADER -#include "memory_wrapper.hpp" - -namespace cubmethod -{ - int - mcon_send_buffer_to_java (SOCKET socket, const cubmem::block &blk) - { - int error = NO_ERROR; - OR_ALIGNED_BUF (OR_INT_SIZE) a_request; - char *request = OR_ALIGNED_BUF_START (a_request); - - int request_size = (int) blk.dim; - or_pack_int (request, request_size); - - int nbytes = jsp_writen (socket, request, OR_INT_SIZE); - if (nbytes != OR_INT_SIZE) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, nbytes); - error = er_errid (); - return error; - } - - nbytes = jsp_writen (socket, blk.ptr, blk.dim); - if (nbytes != (int) blk.dim) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, nbytes); - error = er_errid (); - } - return error; - } - - int mcon_read_data_from_java (const SOCKET socket, cubmem::extensible_block &b) - { - int res_size = 0; - int nbytes = 0; - - nbytes = jsp_readn_with_timeout (socket, (char *) &res_size, OR_INT_SIZE, -1); - if (nbytes != OR_INT_SIZE) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, nbytes); - return er_errid (); - } - - res_size = ntohl (res_size); - if (res_size > 0) - { - cubmem::extensible_block ext_blk; - ext_blk.extend_to (res_size); - - nbytes = jsp_readn_with_timeout (socket, ext_blk.get_ptr (), res_size, -1); - if (nbytes != res_size) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, - nbytes); - return er_errid (); - } - - b = std::move (ext_blk); - } - return NO_ERROR; - } - - int mcon_read_data_from_java (const SOCKET socket, cubmem::block &b) - { - int res_size = 0; - int nbytes = 0; - - nbytes = jsp_readn_with_timeout (socket, (char *) &res_size, OR_INT_SIZE, -1); - if (nbytes != OR_INT_SIZE) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, nbytes); - return er_errid (); - } - - res_size = ntohl (res_size); - if (res_size > 0) - { - cubmem::extensible_block ext_blk; - ext_blk.extend_to (res_size); - - nbytes = jsp_readn_with_timeout (socket, ext_blk.get_ptr (), res_size, -1); - if (nbytes != res_size) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, - nbytes); - return er_errid (); - } - - cubmem::block blk (res_size, ext_blk.release_ptr()); - b = std::move (blk); - } - - return NO_ERROR; - } - - int mcon_read_data_from_java (const SOCKET socket, cubmem::block &b, const mcon_callback_func &interrupt_func) - { - int res_size = 0; - int nbytes = 0; - do - { - int status = interrupt_func (); - if (status != NO_ERROR) - { - return status; - } - - nbytes = jsp_readn (socket, (char *) &res_size, OR_INT_SIZE); - if (nbytes < 0 && errno == ETIMEDOUT) - { - continue; - } - else if (nbytes != OR_INT_SIZE) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, nbytes); - return er_errid (); - } - } - while (nbytes < 0 && errno == ETIMEDOUT); - - res_size = ntohl (res_size); - if (res_size > 0) - { - do - { - int status = interrupt_func (); - if (status != NO_ERROR) - { - return status; - } - - cubmem::extensible_block ext_blk; - ext_blk.extend_to (res_size); - - nbytes = jsp_readn (socket, ext_blk.get_ptr (), res_size); - if (nbytes < 0 && errno == ETIMEDOUT) - { - continue; - } - else if (nbytes != res_size) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, - nbytes); - return er_errid (); - } - - cubmem::block blk (res_size, ext_blk.release_ptr()); - b = std::move (blk); - } - while (nbytes < 0 && errno == ETIMEDOUT); - } - - return NO_ERROR; - } - - -} // namespace cubmethod diff --git a/src/method/method_connection_java.hpp b/src/method/method_connection_java.hpp deleted file mode 100644 index 437492dc48f..00000000000 --- a/src/method/method_connection_java.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * method_connection_java.hpp: Interface to communicate with Java SP Server - */ - -#ifndef _METHOD_CONNECTION_JAVA_HPP_ -#define _METHOD_CONNECTION_JAVA_HPP_ - -#include "porting.h" - -#include "method_connection.hpp" - -#include - -#include "jsp_comm.h" -#include "object_representation.h" /* OR_ */ - -namespace cubmethod -{ - using mcon_callback_func = std::function ; - using mcon_callback_func_with_sock = std::function ; - - ////////////////////////////////////////////////////////////////////////// - // Interface to communicate with Java SP Server - ////////////////////////////////////////////////////////////////////////// - EXPORT_IMPORT int mcon_send_buffer_to_java (SOCKET socket, const cubmem::block &blk); - - template - int mcon_send_data_to_java (SOCKET socket, Args &&... args) - { - cubmem::block b = std::move (mcon_pack_data_block (std::forward (args)...)); - int status = mcon_send_buffer_to_java (socket, b); - if (b.is_valid ()) - { - delete [] b.ptr; - b.ptr = NULL; - b.dim = 0; - } - return status; - } - - EXPORT_IMPORT int mcon_read_data_from_java (const SOCKET socket, cubmem::extensible_block &b); - - EXPORT_IMPORT int mcon_read_data_from_java (const SOCKET socket, cubmem::block &b); - EXPORT_IMPORT int mcon_read_data_from_java (const SOCKET socket, cubmem::block &b, - const mcon_callback_func &interrupt_func); -} - -#endif // _METHOD_CONNECTION_JAVA_HPP_ diff --git a/src/method/method_connection_pool.cpp b/src/method/method_connection_pool.cpp deleted file mode 100644 index 9bea3f8e2a5..00000000000 --- a/src/method/method_connection_pool.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "method_connection_pool.hpp" - -#include "boot_sr.h" -#include "jsp_sr.h" /* jsp_server_port(), jsp_connect_server() */ -#include "jsp_comm.h" /* jsp_disconnect_server (), jsp_ping () */ -#include "jsp_file.h" /* javasp_read_info() */ - -#if defined (SERVER_MODE) -#include "server_support.h" -#endif -// XXX: SHOULD BE THE LAST INCLUDE HEADER -#include "memory_wrapper.hpp" - -namespace cubmethod -{ - connection_pool::connection_pool (int pool_size) - : m_pool_size (pool_size) - , m_queue () - , m_mutex () - { - // - } - - connection_pool::~connection_pool () - { - while (!m_queue.empty ()) - { - connection *conn = m_queue.front (); - m_queue.pop (); - delete conn; - } - } - - connection * - connection_pool::claim () - { - std::unique_lock ulock (m_mutex); - - if (!m_queue.empty ()) - { - connection *conn = m_queue.front (); - m_queue.pop (); - ulock.unlock (); - - // test socket - if (conn->is_valid() == false) - { - jsp_disconnect_server (conn->m_socket); // disconnect connecting with ExecuteThread in invalid state - conn->m_socket = jsp_connect_server (boot_db_name (), jsp_server_port_from_info ()); - } - - return conn; - } - - // new connection - SOCKET socket = jsp_connect_server (boot_db_name (), jsp_server_port_from_info ()); - return new connection (this, socket); - } - - void - connection_pool::retire (connection *&claimed, bool kill) - { - std::unique_lock ulock (m_mutex); - if (claimed == nullptr) - { - return; - } - - // test connection - if (kill == false && claimed->is_valid () == true) - { - if ((int) m_queue.size () < m_pool_size) - { - m_queue.push (claimed); - return; - } - else - { - // overflow - kill = true; - } - } - - if (kill) - { - assert (claimed != nullptr); - if (claimed) - { - delete claimed; - claimed = nullptr; - } - } - } - - int - connection_pool::max_size () const - { - return m_pool_size; - } - - connection::connection (connection_pool *pool, SOCKET socket) - : m_pool (pool), m_socket (socket) - { - // - } - - connection::~connection () - { - m_pool = nullptr; - jsp_disconnect_server (m_socket); - } - - bool - connection::is_valid () - { - return (m_socket != INVALID_SOCKET); - } - - SOCKET - connection::get_socket () - { - return m_socket; - } - - bool - connection::is_jvm_running () - { - JAVASP_SERVER_INFO info; - javasp_read_info (boot_db_name (), info); - if (info.pid == -1) - { - return false; - } - else - { - return true; - } - } - -} // namespace cubmethod diff --git a/src/method/method_connection_pool.hpp b/src/method/method_connection_pool.hpp deleted file mode 100644 index 9a4767fb35e..00000000000 --- a/src/method/method_connection_pool.hpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * method_connection_pool.hpp - */ - -#ifndef _METHOD_CONNECTION_POOL_HPP_ -#define _METHOD_CONNECTION_POOL_HPP_ - -#if !defined (SERVER_MODE) && !defined (SA_MODE) -#error Belongs to server module -#endif /* !defined (SERVER_MODE) && !defined (SA_MODE) */ - -#include -#include - -#include "porting.h" // SOCKET - -namespace cubmethod -{ - // forward declaration - class connection; - - class connection_pool - { - public: - connection_pool () = delete; - explicit connection_pool (int pool_size); - ~connection_pool (); - - connection_pool (connection_pool &&other) = delete; // Not MoveConstructible - connection_pool (const connection_pool ©) = delete; // Not CopyConstructible - - connection_pool &operator= (connection_pool &&other) = delete; // Not MoveAssignable - connection_pool &operator= (const connection_pool ©) = delete; // Not CopyAssignable - - connection *claim (); - void retire (connection *&claimed, bool kill); - - int max_size () const; - - private: - int m_pool_size; - std::queue m_queue; - std::mutex m_mutex; - }; - - class connection - { - - friend connection_pool; - - public: - connection () = delete; - ~connection (); - - connection (const connection ©) = delete; // Not CopyConstructible - connection &operator= (const connection ©) = delete; // Not CopyAssignable - - connection (connection &&c) = default; - connection &operator= (connection &&other) = delete; - - bool is_valid (); - SOCKET get_socket (); - bool is_jvm_running (); - - private: - explicit connection (connection_pool *pool, SOCKET socket); - - connection_pool *m_pool; - SOCKET m_socket; - }; -} // namespace cubmethod - -#endif // _METHOD_CONNECTION_POOL_HPP_ diff --git a/src/method/method_connection_sr.cpp b/src/method/method_connection_sr.cpp deleted file mode 100644 index 4f137c78e49..00000000000 --- a/src/method/method_connection_sr.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "method_connection_sr.hpp" - -#include "porting.h" -#if defined (SERVER_MODE) -#include "network.h" /* METHOD_CALL */ -#include "network_interface_sr.h" /* xs_receive_data_from_client() */ -#include "server_support.h" /* css_send_reply_and_data_to_client(), css_get_comm_request_id() */ -#else -#include "query_method.hpp" -#include "method_callback.hpp" -#endif - -#include "object_representation.h" /* OR_ */ -#include "jsp_comm.h" /* jsp_writen() */ -// XXX: SHOULD BE THE LAST INCLUDE HEADER -#include "memory_wrapper.hpp" - -namespace cubmethod -{ -////////////////////////////////////////////////////////////////////////// -// General interface to communicate with CAS -////////////////////////////////////////////////////////////////////////// -#if defined (SERVER_MODE) - int xs_send (cubthread::entry *thread_p, const cubmem::extensible_block &mem) - { - OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply; - char *reply = OR_ALIGNED_BUF_START (a_reply); - - /* pack headers */ - char *ptr = or_pack_int (reply, (int) METHOD_CALL); - ptr = or_pack_int (ptr, (int) mem.get_size ()); - -#if !defined(NDEBUG) - /* suppress valgrind UMW error */ - memset (ptr, 0, OR_ALIGNED_BUF_SIZE (a_reply) - (ptr - reply)); -#endif - - if (thread_p == NULL || thread_p->conn_entry == NULL) - { - return ER_FAILED; - } - - /* send */ - unsigned int rid = css_get_comm_request_id (thread_p); - return css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), - (char * )mem.get_read_ptr(), (int) mem.get_size ()); - } - - int xs_receive (cubthread::entry *thread_p, const xs_callback_func &func) - { - cubmem::block buffer (0, nullptr); - - int error = xs_receive_data_from_client (thread_p, &buffer.ptr, (int *) &buffer.dim); - if (error == NO_ERROR && er_errid () == NO_ERROR) - { - error = func (buffer); - } - else - { - if (error == NO_ERROR) - { - error = er_errid (); // ER_SP_TOO_MANY_NESTED_CALL, ER_INTERRUPTED... (interrupt reasons) - } - } - - free_and_init (buffer.ptr); - return error; - } - - int xs_receive (cubthread::entry *thread_p, SOCKET socket, const xs_callback_func_with_sock &func) - { - cubmem::block buffer (0, nullptr); - - int error = xs_receive_data_from_client (thread_p, &buffer.ptr, (int *) &buffer.dim); - if (error == NO_ERROR && er_errid () == NO_ERROR) - { - error = func (socket, buffer); - } - else - { - if (error == NO_ERROR) - { - error = er_errid (); // ER_SP_TOO_MANY_NESTED_CALL, ER_INTERRUPTED... (interrupt reasons) - } - } - - free_and_init (buffer.ptr); - return error; - } -#else // SA_MODE - int xs_send (cubthread::entry *thread_p, const cubmem::extensible_block &ext_blk) - { - packing_unpacker unpacker (ext_blk.get_read_ptr (), ext_blk.get_size ()); - return method_dispatch (unpacker); - } - - int xs_receive (cubthread::entry *thread_p, const xs_callback_func &func) - { - std::queue &queue = mcon_get_data_queue (); - - assert (!queue.empty()); - - cubmem::extensible_block &blk = queue.front (); - cubmem::block buffer (blk.get_size(), blk.get_ptr()); - int error = func (buffer); - - queue.pop (); - return error; - } - - int xs_receive (cubthread::entry *thread_p, SOCKET socket, const xs_callback_func_with_sock &func) - { - std::queue &queue = mcon_get_data_queue (); - - assert (!queue.empty()); - - cubmem::extensible_block &blk = queue.front (); - cubmem::block buffer (blk.get_size(), blk.get_ptr()); - - int error = func (socket, buffer); - - queue.pop (); - return error; - } -#endif -} // namespace cubmethod diff --git a/src/method/method_connection_sr.hpp b/src/method/method_connection_sr.hpp deleted file mode 100644 index 94d79e71100..00000000000 --- a/src/method/method_connection_sr.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * method_connection_sr.hpp - */ - -#ifndef _METHOD_CONNECTION_SR_HPP_ -#define _METHOD_CONNECTION_SR_HPP_ - -#ident "$Id$" - -#if !defined (SERVER_MODE) && !defined (SA_MODE) -#error Belongs to server module -#endif /* !defined (SERVER_MODE) && !defined (SA_MODE) */ - -#include - -#include "porting.h" -#include "method_connection.hpp" - -// thread_entry.hpp -namespace cubthread -{ - class entry; -} - -namespace cubmem -{ - class block; -} - -namespace cubmethod -{ - using xs_callback_func = std::function ; - using xs_callback_func_with_sock = std::function ; - - ////////////////////////////////////////////////////////////////////////// - // Interface to communicate with CAS - ////////////////////////////////////////////////////////////////////////// - int xs_receive (cubthread::entry *thread_p, const xs_callback_func &func); - int xs_receive (cubthread::entry *thread_p, SOCKET socket, const xs_callback_func_with_sock &func); - int xs_send (cubthread::entry *thread_p, const cubmem::extensible_block &mem); - template - int method_send_data_to_client (cubthread::entry *thread_p, Args &&... args) - { - const cubmem::extensible_block b = std::move (mcon_pack_data (std::forward (args)...)); - return xs_send (thread_p, b); - } -} - -#endif // _METHOD_CONNECTION_SR_HPP_ diff --git a/src/method/method_def.cpp b/src/method/method_def.cpp deleted file mode 100644 index f42748cd868..00000000000 --- a/src/method/method_def.cpp +++ /dev/null @@ -1,434 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "method_def.hpp" - -#include "memory_private_allocator.hpp" -// XXX: SHOULD BE THE LAST INCLUDE HEADER -#include "memory_wrapper.hpp" - -method_sig_node::method_sig_node () -{ - next = nullptr; - method_name = nullptr; - method_type = METHOD_TYPE_NONE; - num_method_args = 0; - method_arg_pos = nullptr; -} - -method_sig_node::~method_sig_node () -{ - freemem (); -} - -method_sig_node::method_sig_node (method_sig_node &&obj) -{ - next = std::move (obj.next); - - method_name = obj.method_name; - method_type = obj.method_type; - method_arg_pos = obj.method_arg_pos; - num_method_args = obj.num_method_args; - - obj.method_name = nullptr; - obj.method_arg_pos = nullptr; - - if (method_type == METHOD_TYPE_NONE) - { - // - } - else if (method_type != METHOD_TYPE_JAVA_SP) - { - class_name = obj.class_name; - obj.class_name = nullptr; - } - else - { - arg_info.arg_mode = obj.arg_info.arg_mode; - arg_info.arg_type = obj.arg_info.arg_type; - - obj.arg_info.arg_mode = nullptr; - obj.arg_info.arg_type = nullptr; - } -} - -method_sig_node::method_sig_node (const method_sig_node &obj) -{ - if (obj.next != nullptr) - { - next = (METHOD_SIG *) db_private_alloc (NULL, sizeof (METHOD_SIG)); - *next = * (obj.next); - } - else - { - next = nullptr; - } - - if (obj.method_name != nullptr) - { - int method_name_len = strlen (obj.method_name); - method_name = (char *) db_private_alloc (NULL, method_name_len + 1); - strncpy (method_name, obj.method_name, method_name_len); - } - - method_type = obj.method_type; - num_method_args = obj.num_method_args; - - if (obj.num_method_args > 0) - { - method_arg_pos = (int *) db_private_alloc (NULL, sizeof (int) * (num_method_args + 1)); - for (int n = 0; n < num_method_args + 1; n++) - { - method_arg_pos[n] = obj.method_arg_pos[n]; - } - } - - if (method_type == METHOD_TYPE_NONE) - { - // - } - else if (method_type != METHOD_TYPE_JAVA_SP) - { - if (obj.class_name != nullptr) - { - int class_name_len = strlen (obj.class_name); - class_name = (char *) db_private_alloc (NULL, class_name_len + 1); - strncpy (class_name, obj.class_name, class_name_len); - } - } - else - { - if (num_method_args > 0) - { - arg_info.arg_mode = (int *) db_private_alloc (NULL, sizeof (int) * (num_method_args)); - arg_info.arg_type = (int *) db_private_alloc (NULL, sizeof (int) * (num_method_args)); - for (int n = 0; n < num_method_args; n++) - { - arg_info.arg_mode[n] = obj.arg_info.arg_mode[n]; - arg_info.arg_type[n] = obj.arg_info.arg_type[n]; - } - } - else - { - arg_info.arg_mode = nullptr; - arg_info.arg_type = nullptr; - } - } -} - -void -method_sig_node::pack (cubpacking::packer &serializator) const -{ - serializator.pack_c_string (method_name, strlen (method_name)); - - serializator.pack_int (method_type); - serializator.pack_int (num_method_args); - - for (int i = 0; i < num_method_args + 1; i++) - { - serializator.pack_int (method_arg_pos[i]); - } - - if (method_type == METHOD_TYPE_NONE) - { - // - } - else if (method_type != METHOD_TYPE_JAVA_SP) - { - serializator.pack_c_string (class_name, strlen (class_name)); - } - else - { - for (int i = 0; i < num_method_args; i++) - { - serializator.pack_int (arg_info.arg_mode[i]); - } - for (int i = 0; i < num_method_args; i++) - { - serializator.pack_int (arg_info.arg_type[i]); - } - serializator.pack_int (arg_info.result_type); - } -} - -size_t -method_sig_node::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const -{ - size_t size = serializator.get_packed_int_size (start_offset); /* num_methods */ - - size += serializator.get_packed_c_string_size (method_name, strlen (method_name), size); - - /* method type and num_method_args */ - size += serializator.get_packed_int_size (size); - size += serializator.get_packed_int_size (size); - - for (int i = 0; i < num_method_args + 1; i++) - { - size += serializator.get_packed_int_size (size); /* method_sig->method_arg_pos[i] */ - } - - if (method_type == METHOD_TYPE_NONE) - { - // - } - else if (method_type != METHOD_TYPE_JAVA_SP) - { - size += serializator.get_packed_c_string_size (class_name, strlen (class_name), size); - } - else - { - for (int i = 0; i < num_method_args; i++) - { - size += serializator.get_packed_int_size (size); /* method_sig->arg_info.arg_mode[i] */ - size += serializator.get_packed_int_size (size); /* method_sig->arg_info.arg_type[i] */ - } - size += serializator.get_packed_int_size (size); /* method_sig->arg_info.result_type */ - } - - return size; -} - -method_sig_node & -method_sig_node::operator= (const method_sig_node &obj) -{ - if (this != &obj) - { - if (obj.next != nullptr) - { - next = (METHOD_SIG *) db_private_alloc (NULL, sizeof (METHOD_SIG)); - *next = * (obj.next); - } - else - { - next = nullptr; - } - - if (obj.method_name != nullptr) - { - int method_name_len = strlen (obj.method_name); - method_name = (char *) db_private_alloc (NULL, method_name_len + 1); - strncpy (method_name, obj.method_name, method_name_len); - } - - method_type = obj.method_type; - num_method_args = obj.num_method_args; - if (obj.num_method_args > 0) - { - - method_arg_pos = (int *) db_private_alloc (NULL, sizeof (int) * (num_method_args + 1)); - for (int n = 0; n < num_method_args + 1; n++) - { - method_arg_pos[n] = obj.method_arg_pos[n]; - } - } - - if (method_type == METHOD_TYPE_NONE) - { - // - } - else if (method_type != METHOD_TYPE_JAVA_SP) - { - if (obj.class_name != nullptr) - { - int class_name_len = strlen (obj.class_name); - class_name = (char *) db_private_alloc (NULL, class_name_len + 1); - strncpy (class_name, obj.class_name, class_name_len); - } - } - else - { - if (num_method_args > 0) - { - arg_info.arg_mode = (int *) db_private_alloc (NULL, sizeof (int) * (num_method_args)); - arg_info.arg_type = (int *) db_private_alloc (NULL, sizeof (int) * (num_method_args)); - for (int n = 0; n < num_method_args; n++) - { - arg_info.arg_mode[n] = obj.arg_info.arg_mode[n]; - arg_info.arg_type[n] = obj.arg_info.arg_type[n]; - } - } - else - { - arg_info.arg_mode = nullptr; - arg_info.arg_type = nullptr; - } - } - } - return *this; -} - -void -method_sig_node::unpack (cubpacking::unpacker &deserializator) -{ - next = nullptr; - - cubmem::extensible_block method_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR }; - deserializator.unpack_string_to_memblock (method_name_blk); - method_name = method_name_blk.release_ptr (); - - int type; - deserializator.unpack_int (type); - method_type = static_cast (type); - deserializator.unpack_int (num_method_args); - - method_arg_pos = (int *) db_private_alloc (NULL, sizeof (int) * (num_method_args + 1)); - for (int n = 0; n < num_method_args + 1; n++) - { - deserializator.unpack_int (method_arg_pos[n]); - } - - if (method_type == METHOD_TYPE_NONE) - { - // - } - else if (method_type != METHOD_TYPE_JAVA_SP) - { - class_name = nullptr; - cubmem::extensible_block class_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR }; - deserializator.unpack_string_to_memblock (class_name_blk); - class_name = class_name_blk.release_ptr (); - } - else - { - if (num_method_args > 0) - { - arg_info.arg_mode = (int *) db_private_alloc (NULL, sizeof (int) * (num_method_args)); - arg_info.arg_type = (int *) db_private_alloc (NULL, sizeof (int) * (num_method_args)); - - for (int i = 0; i < num_method_args; i++) - { - deserializator.unpack_int (arg_info.arg_mode[i]); - } - - for (int i = 0; i < num_method_args; i++) - { - deserializator.unpack_int (arg_info.arg_type[i]); - } - } - else - { - arg_info.arg_mode = nullptr; - arg_info.arg_type = nullptr; - } - - deserializator.unpack_int (arg_info.result_type); - } -} - -void -method_sig_node::freemem () -{ - if (method_name != nullptr) - { - db_private_free_and_init (NULL, method_name); - } - - if (method_arg_pos != nullptr) - { - db_private_free_and_init (NULL, method_arg_pos); - } - - if (method_type == METHOD_TYPE_NONE) - { - // - } - else if (method_type != METHOD_TYPE_JAVA_SP) - { - if (class_name != nullptr) - { - db_private_free_and_init (NULL, class_name); - } - } - else - { - if (arg_info.arg_mode != nullptr) - { - db_private_free_and_init (NULL, arg_info.arg_mode); - } - if (arg_info.arg_type != nullptr) - { - db_private_free_and_init (NULL, arg_info.arg_type); - } - } -} - -void -method_sig_list::freemem () -{ - METHOD_SIG *sig = method_sig; - while (sig) - { - METHOD_SIG *next = sig->next; - - sig->freemem (); - db_private_free_and_init (NULL, sig); /* itself */ - - sig = next; - } -} - -void -method_sig_list::pack (cubpacking::packer &serializator) const -{ - serializator.pack_int (num_methods); - - METHOD_SIG *sig_p = method_sig; - while (sig_p) - { - sig_p->pack (serializator); - sig_p = sig_p->next; - } -} - -size_t -method_sig_list::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const -{ - size_t size = serializator.get_packed_int_size (start_offset); /* num_methods */ - - METHOD_SIG *sig_p = method_sig; - while (sig_p) - { - size += sig_p->get_packed_size (serializator, size); - sig_p = sig_p->next; - } - return size; -} - -void -method_sig_list::unpack (cubpacking::unpacker &deserializator) -{ - deserializator.unpack_int (num_methods); - - method_sig = nullptr; - if (num_methods > 0) - { - method_sig = (METHOD_SIG *) db_private_alloc (NULL, sizeof (METHOD_SIG)); - METHOD_SIG *method_sig_p = method_sig; - for (int i = 0; i < num_methods; i++) - { - method_sig_p->unpack (deserializator); - - if (i != num_methods - 1) /* last */ - { - method_sig_p->next = (METHOD_SIG *) db_private_alloc (NULL, sizeof (METHOD_SIG)); - } - - method_sig_p = method_sig_p->next; - } - } -} diff --git a/src/method/method_def.hpp b/src/method/method_def.hpp deleted file mode 100644 index 406aeb870c8..00000000000 --- a/src/method/method_def.hpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2008 Search Solution Corporation - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// -// method_def.hpp - define structures used by method feature -// - -#ifndef _METHOD_DEF_H_ -#define _METHOD_DEF_H_ - -#include - -#include "packer.hpp" -#include "packable_object.hpp" - -#define METHOD_MAX_RECURSION_DEPTH 15 - -using METHOD_GROUP_ID = std::uint64_t; -using METHOD_REQ_ID = int; - -typedef enum -{ - METHOD_SUCCESS = 1, - METHOD_EOF, - METHOD_ERROR -} METHOD_CALL_STATUS; - -enum METHOD_TYPE -{ - METHOD_TYPE_NONE = 0, - METHOD_TYPE_INSTANCE_METHOD, - METHOD_TYPE_CLASS_METHOD, - METHOD_TYPE_JAVA_SP -}; - -enum METHOD_REQUEST -{ - METHOD_REQUEST_ARG_PREPARE = 0x40, - METHOD_REQUEST_INVOKE = 0x01, - METHOD_REQUEST_CALLBACK = 0x08, - METHOD_REQUEST_END = 0x20, - - METHOD_REQUEST_COMPILE = 0x80, - METHOD_REQUEST_SQL_SEMANTICS = 0xA0, - METHOD_REQUEST_GLOBAL_SEMANTICS = 0xA1 -}; - -enum METHOD_RESPONSE -{ - METHOD_RESPONSE_SUCCESS, - METHOD_RESPONSE_ERROR -}; - -enum METHOD_CALLBACK_RESPONSE -{ - METHOD_CALLBACK_END_TRANSACTION = 1, - METHOD_CALLBACK_QUERY_PREPARE = 2, - METHOD_CALLBACK_QUERY_EXECUTE = 3, - METHOD_CALLBACK_GET_DB_PARAMETER = 4, - - METHOD_CALLBACK_CURSOR = 7, - METHOD_CALLBACK_FETCH = 8, - METHOD_CALLBACK_GET_SCHEMA_INFO = 9, - - METHOD_CALLBACK_OID_GET = 10, - METHOD_CALLBACK_OID_PUT = 11, - METHOD_CALLBACK_OID_CMD = 17, - METHOD_CALLBACK_COLLECTION = 18, - - // METHOD_CALLBACK_GET_DB_VERSION = 15, - - METHOD_CALLBACK_NEXT_RESULT = 19, - - METHOD_CALLBACK_EXECUTE_BATCH = 20, - METHOD_CALLBACK_EXECUTE_ARRAY = 21, - - METHOD_CALLBACK_CURSOR_UPDATE = 22, - - METHOD_CALLBACK_MAKE_OUT_RS = 33, - METHOD_CALLBACK_GET_GENERATED_KEYS = 34, - - METHOD_CALLBACK_LOB_NEW = 35, - METHOD_CALLBACK_LOB_WRITE = 36, - METHOD_CALLBACK_LOB_READ = 37, - - METHOD_CALLBACK_CURSOR_CLOSE = 42, - - // COMPILE - METHOD_CALLBACK_GET_SQL_SEMANTICS = 100, - METHOD_CALLBACK_GET_GLOBAL_SEMANTICS = 101, -}; - -enum METHOD_ARG_MODE -{ - METHOD_ARG_MODE_IN = 1, - METHOD_ARG_MODE_OUT, - METHOD_ARG_MODE_INOUT -}; - -typedef struct method_arg_info METHOD_ARG_INFO; -struct method_arg_info -{ - int *arg_mode; /* IN, OUT, INOUT */ - int *arg_type; /* DB_TYPE */ - int result_type; /* DB_TYPE */ - - method_arg_info () = default; -}; - -typedef struct method_sig_node METHOD_SIG; -struct method_sig_node -{ - /* method signature */ - METHOD_SIG *next; - char *method_name; /* method name */ - METHOD_TYPE method_type; /* instance or class method */ - int num_method_args; /* number of arguments */ - int *method_arg_pos; /* arg position in list file */ - - union - { - char *class_name; /* class name for the class method */ - METHOD_ARG_INFO arg_info; /* argument info for javasp's server-side calling */ - }; - - void pack (cubpacking::packer &serializator) const; - void unpack (cubpacking::unpacker &deserializator); - size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset = 0) const; - - void freemem (); - - method_sig_node &operator= (const method_sig_node &rhs); - - method_sig_node (); - method_sig_node (method_sig_node &&); // move constructor - method_sig_node (const method_sig_node &obj); // copy constructor - ~method_sig_node (); -}; - -struct method_sig_list : public cubpacking::packable_object -{ - /* signature for methods */ - METHOD_SIG *method_sig; /* one method signature */ - int num_methods; /* number of signatures */ - - void pack (cubpacking::packer &serializator) const; - void unpack (cubpacking::unpacker &deserializator); - size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset = 0) const; - - void freemem (); - - method_sig_list () = default; -}; -typedef struct method_sig_list METHOD_SIG_LIST; - -#endif // _METHOD_DEF_H_ diff --git a/src/method/method_invoke.hpp b/src/method/method_invoke.hpp deleted file mode 100644 index 91f409ec051..00000000000 --- a/src/method/method_invoke.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef _METHOD_INVOKE_HPP_ -#define _METHOD_INVOKE_HPP_ - -#ident "$Id$" - -#if !defined (SERVER_MODE) && !defined (SA_MODE) -#error Belongs to server module -#endif /* !defined (SERVER_MODE) && !defined (SA_MODE) */ - -#include -#include -#include - -#include "dbtype.h" /* db_value_* */ -#include "method_def.hpp" /* method_sig_node */ -#include "method_query_cursor.hpp" -#include "method_struct_invoke.hpp" /* cubmethod::header */ -#include "mem_block.hpp" /* cubmem::block, cubmem::extensible_block */ -#include "porting.h" /* SOCKET */ - -#if defined (SA_MODE) -#include "query_method.hpp" -#endif - -// thread_entry.hpp -namespace cubthread -{ - class entry; -} - -namespace cubmethod -{ - // forward declarations - class method_invoke_group; - - class method_invoke - { - public: - method_invoke () = delete; // Not DefaultConstructible - method_invoke (method_invoke_group *group, method_sig_node *sig) : m_group (group), m_method_sig (sig) {} - virtual ~method_invoke () {}; - - method_invoke (method_invoke &&other) = delete; // Not MoveConstructible - method_invoke (const method_invoke ©) = delete; // Not CopyConstructible - - method_invoke &operator= (method_invoke &&other) = delete; // Not MoveAssignable - method_invoke &operator= (const method_invoke ©) = delete; // Not CopyAssignable - - virtual int invoke (cubthread::entry *thread_p, std::vector> &arg_base) = 0; - virtual int get_return (cubthread::entry *thread_p, std::vector> &arg_base, - DB_VALUE &result) = 0; - - uint64_t get_id () - { - return (uint64_t) this; - } - - protected: - method_invoke_group *m_group; - method_sig_node *m_method_sig; - }; - - class method_invoke_builtin : public method_invoke - { - public: - method_invoke_builtin () = delete; - method_invoke_builtin (method_invoke_group *group, method_sig_node *method_sig); - - int invoke (cubthread::entry *thread_p, std::vector> &arg_base) override; - int get_return (cubthread::entry *thread_p, std::vector> &arg_base, - DB_VALUE &result) override; - }; - - class method_invoke_java : public method_invoke - { - public: - method_invoke_java () = delete; - method_invoke_java (method_invoke_group *group, method_sig_node *method_sig, bool transaction_control); - ~method_invoke_java (); - - int invoke (cubthread::entry *thread_p, std::vector> &arg_base) override; - int get_return (cubthread::entry *thread_p, std::vector> &arg_base, - DB_VALUE &result) override; - - private: - int receive_result (std::vector> &arg_base, - DB_VALUE &returnval); - int receive_error (); - - int callback_dispatch (cubthread::entry &thread_ref); - - int callback_get_db_parameter (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_prepare (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_execute (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_fetch (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_oid_get (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_oid_put (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_oid_cmd (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_collection_cmd (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_make_outresult (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_get_generated_keys (cubthread::entry &thread_ref, packing_unpacker &unpacker); - int callback_end_transaction (cubthread::entry &thread_ref, packing_unpacker &unpacker); - - void erase_query_cursor (const std::uint64_t query_id); - - const cubmethod::header &get_next_java_header (cubmethod::header &header); - - cubmethod::header m_client_header; // header sending to cubridcs - cubmethod::header m_java_header; // header sending to cub_javasp - - bool m_transaction_control; - }; - -} // namespace cubmethod - -#endif /* _METHOD_INVOKE_HPP_ */ diff --git a/src/method/method_invoke_builtin.cpp b/src/method/method_invoke_builtin.cpp deleted file mode 100644 index 13d07f1dae6..00000000000 --- a/src/method/method_invoke_builtin.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "method_invoke.hpp" - -#include - -#include "method_struct_invoke.hpp" -#include "method_invoke_group.hpp" -#include "packer.hpp" -#include "method_connection_sr.hpp" - -#if defined (SERVER_MODE) -#include "method_struct_query.hpp" -#else -#include "query_method.hpp" -#endif -// XXX: SHOULD BE THE LAST INCLUDE HEADER -#include "memory_wrapper.hpp" - -namespace cubmethod -{ - method_invoke_builtin::method_invoke_builtin (method_invoke_group *group, method_sig_node *method_sig) - : method_invoke (group, method_sig) - { - // - } - - int method_invoke_builtin::invoke (cubthread::entry *thread_p, std::vector> &arg_base) - { - int error = NO_ERROR; - cubmethod::header header (m_group->get_session_id(), METHOD_REQUEST_INVOKE /* default */, 0); - cubmethod::invoke_builtin arg (m_group->get_id (), m_method_sig); - error = method_send_data_to_client (thread_p, header, arg); - return error; - } - - int - method_invoke_builtin::get_return (cubthread::entry *thread_p, std::vector> &arg_base, - DB_VALUE &result) - { - int error = NO_ERROR; - db_value_clear (&result); - - auto get_method_result = [&] (cubmem::block & b) - { - int e = NO_ERROR; - packing_unpacker unpacker (b); - int status; - unpacker.unpack_int (status); - if (status == METHOD_SUCCESS) - { - unpacker.unpack_db_value (result); - } - else - { - unpacker.unpack_int (e); /* er_errid */ - } - return e; - }; - - error = xs_receive (thread_p, get_method_result); - return error; - } -} // namespace cubmethod diff --git a/src/method/method_invoke_group.cpp b/src/method/method_invoke_group.cpp deleted file mode 100644 index 90135d5da27..00000000000 --- a/src/method/method_invoke_group.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "method_invoke_group.hpp" - -#include "boot_sr.h" -#include "dbtype.h" /* db_value_* */ -#include "db_value_printer.hpp" -#include "jsp_comm.h" /* common communcation functions for javasp */ -#include "mem_block.hpp" /* cubmem::extensible_block */ -#include "method_invoke.hpp" -#include "method_struct_invoke.hpp" -#include "object_primitive.h" -#include "object_representation.h" /* OR_ */ -#include "packer.hpp" -#include "method_connection_sr.hpp" -#include "method_connection_java.hpp" -#include "method_connection_pool.hpp" -#include "session.h" -#include "string_buffer.hpp" - -#if defined (SA_MODE) -#include "query_method.hpp" -#endif -// XXX: SHOULD BE THE LAST INCLUDE HEADER -#include "memory_wrapper.hpp" - -namespace cubmethod -{ -////////////////////////////////////////////////////////////////////////// -// Method Group to invoke together -////////////////////////////////////////////////////////////////////////// - method_invoke_group::method_invoke_group (cubthread::entry *thread_p, const method_sig_list &sig_list, - bool is_for_scan = false) - : m_id ((std::uint64_t) this) - , m_thread_p (thread_p) - , m_connection (nullptr) - , m_cursor_set () - , m_handler_set () - { - assert (sig_list.num_methods > 0); - - // init runtime context - session_get_method_runtime_context (thread_p, m_rctx); - session_get_session_id (thread_p, &m_sid); - - m_tid = logtb_find_current_tranid (thread_p); - - method_sig_node *sig = sig_list.method_sig; - while (sig) - { - method_invoke *mi = nullptr; - - METHOD_TYPE type = sig->method_type; - switch (type) - { - case METHOD_TYPE_INSTANCE_METHOD: - case METHOD_TYPE_CLASS_METHOD: - mi = new method_invoke_builtin (this, sig); - break; - case METHOD_TYPE_JAVA_SP: - { - bool use_tcl = prm_get_bool_value (PRM_ID_PL_TRANSACTION_CONTROL); - mi = new method_invoke_java (this, sig, use_tcl); - } - break; - default: - assert (false); // not implemented yet - break; - } - - m_kind_type.insert (type); - m_method_vector.push_back (mi); - - sig = sig->next; - } - - DB_VALUE v; - db_make_null (&v); - m_result_vector.resize (sig_list.num_methods, v); - m_is_running = false; - m_parameter_info = nullptr; - m_is_for_scan = is_for_scan; - } - - method_invoke_group::~method_invoke_group () - { - for (method_invoke *method: m_method_vector) - { - delete method; - } - m_method_vector.clear (); - if (m_parameter_info) - { - delete m_parameter_info; - } - } - - DB_VALUE & - method_invoke_group::get_return_value (int index) - { - assert (index >= 0 && index < (int) get_num_methods ()); - return m_result_vector[index]; - } - - int - method_invoke_group::get_num_methods () const - { - return m_method_vector.size (); - } - - METHOD_GROUP_ID - method_invoke_group::get_id () const - { - return m_id; - } - - TRANID - method_invoke_group::get_tran_id () - { - m_tid = logtb_find_current_tranid (m_thread_p); - return m_tid; - } - - SOCKET - method_invoke_group::get_socket () const - { - return m_connection ? m_connection->get_socket () : INVALID_SOCKET; - } - - cubthread::entry * - method_invoke_group::get_thread_entry () const - { - return m_thread_p; - } - - std::queue & - method_invoke_group::get_data_queue () - { - return m_data_queue; - } - - cubmethod::runtime_context * - method_invoke_group::get_runtime_context () - { - return m_rctx; - } - - connection_pool & - method_invoke_group::get_connection_pool () - { - return get_runtime_context ()->get_connection_pool (); - } - - bool - method_invoke_group::is_running () const - { - return m_is_running; - } - - bool - method_invoke_group::is_for_scan () const - { - return m_is_for_scan; - } - - db_parameter_info * - method_invoke_group::get_db_parameter_info () const - { - return m_parameter_info; - } - - void - method_invoke_group::set_db_parameter_info (db_parameter_info *param_info) - { - m_parameter_info = param_info; - } - - bool - method_invoke_group::is_supported_dbtype (const DB_VALUE &value) - { - bool res = false; - switch (DB_VALUE_TYPE (&value)) - { - case DB_TYPE_INTEGER: - case DB_TYPE_SHORT: - case DB_TYPE_BIGINT: - case DB_TYPE_FLOAT: - case DB_TYPE_DOUBLE: - case DB_TYPE_MONETARY: - case DB_TYPE_NUMERIC: - case DB_TYPE_CHAR: - case DB_TYPE_NCHAR: - case DB_TYPE_VARNCHAR: - case DB_TYPE_STRING: - - case DB_TYPE_DATE: - case DB_TYPE_TIME: - case DB_TYPE_TIMESTAMP: - case DB_TYPE_DATETIME: - - case DB_TYPE_SET: - case DB_TYPE_MULTISET: - case DB_TYPE_SEQUENCE: - case DB_TYPE_OID: - case DB_TYPE_OBJECT: - - case DB_TYPE_RESULTSET: - case DB_TYPE_NULL: - res = true; - break; - - // unsupported types - case DB_TYPE_BIT: - case DB_TYPE_VARBIT: - case DB_TYPE_TABLE: - case DB_TYPE_BLOB: - case DB_TYPE_CLOB: - case DB_TYPE_TIMESTAMPTZ: - case DB_TYPE_TIMESTAMPLTZ: - case DB_TYPE_DATETIMETZ: - case DB_TYPE_DATETIMELTZ: - case DB_TYPE_JSON: - case DB_TYPE_ENUMERATION: - res = false; - break; - - // obsolete, internal, unused type - case DB_TYPE_ELO: - case DB_TYPE_VARIABLE: - case DB_TYPE_SUB: - case DB_TYPE_POINTER: - case DB_TYPE_ERROR: - case DB_TYPE_VOBJ: - case DB_TYPE_DB_VALUE: - case DB_TYPE_MIDXKEY: - default: - assert (false); - break; - } - - return res; - } - - int - method_invoke_group::prepare (std::vector> &arg_base, - const std::vector &arg_use_vec) - { - int error = NO_ERROR; - - /* send base arguments */ - for (const auto &elem : m_kind_type) - { - switch (elem) - { - case METHOD_TYPE_INSTANCE_METHOD: - case METHOD_TYPE_CLASS_METHOD: - { - cubmethod::header header (get_session_id(), METHOD_REQUEST_ARG_PREPARE, get_and_increment_request_id ()); - cubmethod::prepare_args arg (m_id, get_tran_id (), elem, arg_base); - error = method_send_data_to_client (m_thread_p, header, arg); - break; - } - case METHOD_TYPE_JAVA_SP: - { - /* optimize arguments only for java sp not to send redundant values */ - DB_VALUE null_val; - db_make_null (&null_val); - std::vector> optimized_arg_base (arg_base.begin (), - arg_base.end ()); /* bind null value for the unused columns */ - for (int i = 0; i < arg_use_vec.size (); i++) - { - bool is_used = arg_use_vec [i]; - optimized_arg_base[i] = (!is_used) ? std::ref (null_val) : optimized_arg_base[i]; - } - - /* check unsupported types */ - for (const DB_VALUE &value : optimized_arg_base) - { - if (is_supported_dbtype (value) == false) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_SUPPORTED_ARG_TYPE, 1, - pr_type_name ((DB_TYPE) value.domain.general_info.type)); - set_error_msg (er_msg ()); - return er_errid (); - } - } - - // send to Java SP Servers - cubmethod::header header (get_session_id(), SP_CODE_PREPARE_ARGS, get_and_increment_request_id ()); - cubmethod::prepare_args arg (m_id, get_tran_id (), elem, optimized_arg_base); - - error = mcon_send_data_to_java (get_socket (), header, arg); - break; - } - default: - assert (false); - break; - } - } - - return error; - } - - int method_invoke_group::execute (std::vector> &arg_base) - { - int error = NO_ERROR; - - for (int i = 0; i < get_num_methods (); i++) - { - error = m_method_vector[i]->invoke (m_thread_p, arg_base); - if (error != NO_ERROR) - { - break; - } - - error = m_method_vector[i]->get_return (m_thread_p, arg_base, m_result_vector[i]); - if (m_rctx->is_interrupted ()) - { - error = m_rctx->get_interrupt_id (); - } - - if (error != NO_ERROR) - { - // if error is not interrupt reason, interrupt is not set - m_rctx->set_interrupt (error, (er_has_error () && er_msg ()) ? er_msg () : ""); - break; - } - } - - return error; - } - - void - method_invoke_group::begin () - { - if (m_is_running == true) - { - return; - } - - // push to stack - m_rctx->push_stack (m_thread_p, this); - - // connect socket for java sp - bool is_in = m_kind_type.find (METHOD_TYPE_JAVA_SP) != m_kind_type.end (); - if (is_in) - { - if (m_connection == nullptr) - { - m_connection = get_connection_pool ().claim(); - } - - // check javasp server's status - if (m_connection->get_socket () == INVALID_SOCKET) - { - if (m_connection->is_jvm_running ()) - { - m_rctx->set_interrupt (ER_SP_CANNOT_CONNECT_JVM, "connect ()"); - } - else - { - m_rctx->set_interrupt (ER_SP_NOT_RUNNING_JVM); - } - } - } - - m_is_running = true; - } - - int method_invoke_group::reset (bool is_end_query) - { - int error = NO_ERROR; - - if (!is_end_query) - { - cubmethod::header header (get_session_id(), METHOD_REQUEST_END, get_and_increment_request_id ()); - std::vector handler_vec (m_handler_set.begin (), m_handler_set.end ()); - error = method_send_data_to_client (m_thread_p, header, handler_vec); - m_handler_set.clear (); - } - - destroy_resources (); - - return error; - } - - void - method_invoke_group::register_client_handler (int handler_id) - { - m_handler_set.insert (handler_id); - } - - void - method_invoke_group::end () - { - if (m_is_running == false) - { - return; - } - - // FIXME: The connection is closed to prevent Java thread from entering an unexpected state. - if (m_connection) - { - bool kill = (m_rctx->is_interrupted() || er_has_error ()); - get_connection_pool ().retire (m_connection, kill); - m_connection = nullptr; - } - - // FIXME - // m_rctx->pop_stack (m_thread_p, this); - - m_is_running = false; - } - - void - method_invoke_group::destroy_resources () - { - pr_clear_value_vector (m_result_vector); - - // destroy cursors used in this group - destory_all_cursors (); - } - - query_cursor * - method_invoke_group::create_cursor (QUERY_ID query_id, bool oid_included) - { - if (query_id == NULL_QUERY_ID || query_id >= SHRT_MAX) - { - // false query e.g) SELECT * FROM db_class WHERE 0 <> 0 - assert (query_id == NULL_QUERY_ID); - return nullptr; - } - - m_cursor_set.insert (query_id); - return m_rctx->create_cursor (m_thread_p, query_id, oid_included); - } - - void - method_invoke_group::register_returning_cursor (QUERY_ID query_id) - { - m_rctx->register_returning_cursor (m_thread_p, query_id); - m_cursor_set.erase (query_id); - } - - query_cursor * - method_invoke_group::get_cursor (QUERY_ID query_id) - { - return m_rctx->get_cursor (m_thread_p, query_id); - } - - void - method_invoke_group::destory_all_cursors () - { - for (auto &cursor_it : m_cursor_set) - { - // If the cursor is received from the child function and is not returned to the parent function, the cursor remains in m_cursor_set. - // So here trying to find the cursor Id in the global returning cursor storage and remove it if exists. - m_rctx->deregister_returning_cursor (m_thread_p, cursor_it); - - m_rctx->destroy_cursor (m_thread_p, cursor_it); - } - - m_cursor_set.clear (); - } - - std::string - method_invoke_group::get_error_msg () - { - return m_err_msg; - } - - void - method_invoke_group::set_error_msg (const std::string &msg) - { - m_err_msg = msg; - } -} // namespace cubmethod diff --git a/src/method/method_invoke_java.cpp b/src/method/method_invoke_java.cpp deleted file mode 100644 index a5d146cc371..00000000000 --- a/src/method/method_invoke_java.cpp +++ /dev/null @@ -1,703 +0,0 @@ -/* - * - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "method_invoke.hpp" - -#include - -#include "jsp_comm.h" /* common communcation functions for javasp */ -#include "object_representation.h" /* OR_ */ - -#include "connection_support.h" -#include "dbtype_def.h" - -#include "method_connection_sr.hpp" -#include "method_connection_java.hpp" -#include "method_struct_parameter_info.hpp" -#include "method_struct_invoke.hpp" -#include "method_struct_value.hpp" -#include "method_struct_oid_info.hpp" -#include "method_invoke_group.hpp" -#include "method_struct_query.hpp" -#include "method_query_util.hpp" -#include "method_runtime_context.hpp" - -#include "log_impl.h" - -#if !defined (SERVER_MODE) -#include "method_callback.hpp" -#endif -// XXX: SHOULD BE THE LAST INCLUDE HEADER -#include "memory_wrapper.hpp" - -namespace cubmethod -{ - method_invoke_java::method_invoke_java (method_invoke_group *group, method_sig_node *method_sig, - bool transaction_control) - : method_invoke (group, method_sig) - , m_client_header (group->get_session_id (), METHOD_REQUEST_CALLBACK /* default */, 0) - , m_java_header (group->get_session_id (), SP_CODE_INTERNAL_JDBC /* default */, 0) - , m_transaction_control (transaction_control) - { - // - } - - method_invoke_java::~method_invoke_java () - { - // - } - - const cubmethod::header & - method_invoke_java::get_next_java_header (cubmethod::header &header) - { - header.req_id = m_group->get_and_increment_request_id (); - return header; - } - - int method_invoke_java::invoke (cubthread::entry *thread_p, std::vector> &arg_base) - { - int error = NO_ERROR; - - cubmethod::header header (m_group->get_session_id (), SP_CODE_INVOKE, m_group->get_and_increment_request_id ()); - cubmethod::invoke_java arg (m_group->get_id (), m_group->get_tran_id (), m_method_sig, m_transaction_control); - - error = mcon_send_data_to_java (m_group->get_socket (), header, arg); - return error; - } - - static int - method_interrupt_handler (cubthread::entry *thread_p) - { - cubmethod::runtime_context *rctx = cubmethod::get_rctx (thread_p); - if (rctx && rctx->is_interrupted ()) - { - return rctx->get_interrupt_id (); - } - return NO_ERROR; - } - - int - method_invoke_java::get_return (cubthread::entry *thread_p, std::vector> &arg_base, - DB_VALUE &returnval) - { - int start_code, error_code = NO_ERROR; - - do - { - /* read request code */ - cubmem::block response_blk; - int nbytes = -1; - auto interrupt_f = std::bind (method_interrupt_handler, thread_p); - error_code = mcon_read_data_from_java (m_group->get_socket(), response_blk, interrupt_f); - if (error_code == NO_ERROR) - { - packing_unpacker unpacker (response_blk); - unpacker.unpack_int (start_code); - - char *aligned_ptr = PTR_ALIGN (unpacker.get_curr_ptr(), MAX_ALIGNMENT); - cubmem::block payload_blk ((size_t) (unpacker.get_buffer_end() - aligned_ptr), - aligned_ptr); - m_group->get_data_queue().emplace (std::move (payload_blk)); - - /* processing */ - if (start_code == SP_CODE_INTERNAL_JDBC) - { - error_code = callback_dispatch (*thread_p); - } - else if (start_code == SP_CODE_RESULT) - { - error_code = receive_result (arg_base, returnval); - } - else if (start_code == SP_CODE_ERROR) - { - error_code = receive_error (); - db_make_null (&returnval); - } - else - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, - start_code); - error_code = ER_SP_NETWORK_ERROR; - } - - if (m_group->get_data_queue().empty() == false) - { - m_group->get_data_queue().pop (); - } - } - - // free phase - if (response_blk.is_valid ()) - { - delete [] response_blk.ptr; - response_blk.ptr = NULL; - response_blk.dim = 0; - } - - if (error_code != NO_ERROR) - { - break; - } - } - while (error_code == NO_ERROR && start_code == SP_CODE_INTERNAL_JDBC); - - return error_code; - } - - int - method_invoke_java::receive_result (std::vector> &arg_base, - DB_VALUE &returnval) - { - int error_code = NO_ERROR; - - // check queue - if (m_group->get_data_queue().empty() == true) - { - return ER_FAILED; - } - - cubmem::block &blk = m_group->get_data_queue().front (); - packing_unpacker unpacker (blk); - - dbvalue_java value_unpacker; - db_make_null (&returnval); - value_unpacker.value = &returnval; - value_unpacker.unpack (unpacker); - - if (db_value_type (&returnval) == DB_TYPE_RESULTSET) - { - std::uint64_t query_id = db_get_resultset (&returnval); - m_group->register_returning_cursor (query_id); - } - - /* out arguments */ - DB_VALUE temp; - int num_args = m_method_sig->num_method_args; - for (int i = 0; i < num_args; i++) - { - if (m_method_sig->arg_info.arg_mode[i] == METHOD_ARG_MODE_IN) - { - continue; - } - - value_unpacker.value = &temp; - value_unpacker.unpack (unpacker); - - if (db_value_type (&temp) == DB_TYPE_RESULTSET) - { - // out argument CURSOR is not supported yet - // it is implmented for the future - std::uint64_t query_id = db_get_resultset (&temp); - m_group->register_returning_cursor (query_id); - } - - int pos = m_method_sig->method_arg_pos[i]; - DB_VALUE &arg_ref = arg_base[pos].get(); - db_value_clear (&arg_ref); - db_value_clone (&temp, &arg_ref); - db_value_clear (&temp); - } - - return error_code; - } - - int - method_invoke_java::receive_error () - { - // check queue - if (m_group->get_data_queue().empty() == true) - { - return ER_FAILED; - } - - cubmem::block &blk = m_group->get_data_queue().front (); - - packing_unpacker unpacker (blk); - - std::string error_msg; - unpacker.unpack_string (error_msg); - - m_group->set_error_msg (error_msg); - return ER_FAILED; - } - - int - method_invoke_java::callback_dispatch (cubthread::entry &thread_ref) - { - int error = NO_ERROR; - - // check queue - if (m_group->get_data_queue().empty() == true) - { - return ER_FAILED; - } - - cubmem::block &blk = m_group->get_data_queue().front (); - packing_unpacker unpacker (blk); - - int code; - unpacker.unpack_int (code); - - switch (code) - { - /* NOTE: we don't need to implement it - case METHOD_CALLBACK_GET_DB_VERSION: - break; - */ - - case METHOD_CALLBACK_GET_DB_PARAMETER: - error = callback_get_db_parameter (thread_ref, unpacker); - break; - - case METHOD_CALLBACK_QUERY_PREPARE: - error = callback_prepare (thread_ref, unpacker); - break; - - case METHOD_CALLBACK_QUERY_EXECUTE: - error = callback_execute (thread_ref, unpacker); - break; - - case METHOD_CALLBACK_FETCH: - error = callback_fetch (thread_ref, unpacker); - break; - - case METHOD_CALLBACK_OID_GET: - error = callback_oid_get (thread_ref, unpacker); - break; - - case METHOD_CALLBACK_OID_PUT: - error = callback_oid_put (thread_ref, unpacker); - break; - - case METHOD_CALLBACK_OID_CMD: - error = callback_oid_cmd (thread_ref, unpacker); - break; - - case METHOD_CALLBACK_COLLECTION: - error = callback_collection_cmd (thread_ref, unpacker); - break; - - case METHOD_CALLBACK_MAKE_OUT_RS: - error = callback_make_outresult (thread_ref, unpacker); - break; - - case METHOD_CALLBACK_GET_GENERATED_KEYS: - error = callback_get_generated_keys (thread_ref, unpacker); - break; - case METHOD_CALLBACK_END_TRANSACTION: - error = callback_end_transaction (thread_ref, unpacker); - break; - default: - // TODO: not implemented yet, do we need error handling? - assert (false); - error = ER_FAILED; - break; - } - - return error; - } - - int - method_invoke_java::callback_get_db_parameter (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - int code = METHOD_CALLBACK_GET_DB_PARAMETER; - - if (m_group->get_db_parameter_info () == nullptr) - { - int tran_index = LOG_FIND_THREAD_TRAN_INDEX (m_group->get_thread_entry()); - db_parameter_info *parameter_info = new db_parameter_info (); - - parameter_info->tran_isolation = logtb_find_isolation (tran_index); - parameter_info->wait_msec = logtb_find_wait_msecs (tran_index); - logtb_get_client_ids (tran_index, ¶meter_info->client_ids); - - m_group->set_db_parameter_info (parameter_info); - } - - db_parameter_info *parameter_info = m_group->get_db_parameter_info (); - if (parameter_info) - { - cubmem::block blk = std::move (mcon_pack_data_block (METHOD_RESPONSE_SUCCESS, *parameter_info)); - error = mcon_send_data_to_java (m_group->get_socket(), get_next_java_header (m_java_header), blk); - delete[] blk.ptr; - } - else - { - cubmem::block blk = std::move (mcon_pack_data_block (METHOD_RESPONSE_ERROR, ER_FAILED, "unknown error", - ARG_FILE_LINE)); - error = mcon_send_data_to_java (m_group->get_socket(), get_next_java_header (m_java_header), blk); - delete[] blk.ptr; - } - return error; - } - - int - method_invoke_java::callback_prepare (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - int code = METHOD_CALLBACK_QUERY_PREPARE; - std::string sql; - int flag; - - unpacker.unpack_all (sql, flag); - - error = method_send_data_to_client (&thread_ref, m_client_header, code, sql, flag); - if (error != NO_ERROR) - { - return error; - } - - auto get_prepare_info = [&] (const cubmem::block & b) - { - packing_unpacker unpacker (b.ptr, (size_t) b.dim); - - int res_code; - unpacker.unpack_int (res_code); - - if (res_code == METHOD_RESPONSE_SUCCESS) - { - prepare_info info; - info.unpack (unpacker); - - m_group->register_client_handler (info.handle_id); - } - - error = mcon_send_data_to_java (m_group->get_socket (), get_next_java_header (m_java_header), b); - return error; - }; - - error = xs_receive (&thread_ref, get_prepare_info); - return error; - } - - int - method_invoke_java::callback_execute (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - int code = METHOD_CALLBACK_QUERY_EXECUTE; - execute_request request; - - unpacker.unpack_all (request); - request.has_parameter = 1; - - error = method_send_data_to_client (&thread_ref, m_client_header, code, request); - - request.clear (); - - auto get_execute_info = [&] (const cubmem::block & b) - { - packing_unpacker unpacker (b.ptr, (size_t) b.dim); - - int res_code; - unpacker.unpack_int (res_code); - - if (res_code == METHOD_RESPONSE_SUCCESS) - { - execute_info info; - info.unpack (unpacker); - - query_result_info ¤t_result_info = info.qresult_info; - int stmt_type = current_result_info.stmt_type; - if (stmt_type == CUBRID_STMT_SELECT) - { - std::uint64_t qid = current_result_info.query_id; - bool is_oid_included = current_result_info.include_oid; - (void) m_group->create_cursor (qid, is_oid_included); - } - } - - error = mcon_send_data_to_java (m_group->get_socket (), get_next_java_header (m_java_header), b); - return error; - }; - - if (error == NO_ERROR) - { - error = xs_receive (&thread_ref, get_execute_info); - } - return error; - } - - int - method_invoke_java::callback_fetch (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - int code = METHOD_CALLBACK_FETCH; - std::uint64_t qid; - int pos; - int fetch_count; - int fetch_flag; - - unpacker.unpack_all (qid, pos, fetch_count, fetch_flag); - - /* find query cursor */ - query_cursor *cursor = m_group->get_cursor (qid); - if (cursor == nullptr) - { - assert (false); - error = mcon_send_data_to_java (m_group->get_socket (), METHOD_RESPONSE_ERROR, ER_FAILED, "unknown error", - ARG_FILE_LINE); - return error; - } - - if (cursor->get_is_opened () == false) - { - cursor->open (); - } - - cursor->set_fetch_count (fetch_count); - - fetch_info info; - - SCAN_CODE s_code = S_SUCCESS; - - /* Most cases, fetch_count will be the same value - * To handle an invalid value of fetch_count is set at `cursor->set_fetch_count (fetch_count);` - * Here, I'm going to get the fetch_count from the getter again. - */ - fetch_count = cursor->get_fetch_count (); - - int start_index = cursor->get_current_index (); - while (s_code == S_SUCCESS) - { - s_code = cursor->next_row (); - int tuple_index = cursor->get_current_index (); - if (s_code == S_END) - { - break; - } - - std::vector tuple_values = cursor->get_current_tuple (); - - if (cursor->get_is_oid_included()) - { - /* FIXME!!: For more optimized way, refactoring method_query_cursor is needed */ - OID *oid = cursor->get_current_oid (); - std::vector sub_vector = {tuple_values.begin() + 1, tuple_values.end ()}; - info.tuples.emplace_back (tuple_index, sub_vector, *oid); - } - else - { - info.tuples.emplace_back (tuple_index, tuple_values); - } - - if (tuple_index - start_index >= fetch_count - 1) - { - break; - } - } - - cubmem::block blk = std::move (mcon_pack_data_block (METHOD_RESPONSE_SUCCESS, info)); - error = mcon_send_data_to_java (m_group->get_socket (), get_next_java_header (m_java_header), std::move (blk)); - if (blk.is_valid ()) - { - delete [] blk.ptr; - blk.ptr = NULL; - blk.dim = 0; - } - return error; - } - - int - method_invoke_java::callback_oid_get (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - int code = METHOD_CALLBACK_OID_GET; - oid_get_request request; - request.unpack (unpacker); - - error = method_send_data_to_client (&thread_ref, m_client_header, code, request); - if (error != NO_ERROR) - { - return error; - } - - auto java_lambda = [&] (const cubmem::block & b) - { - return mcon_send_data_to_java (m_group->get_socket(), get_next_java_header (m_java_header), b); - }; - - error = xs_receive (&thread_ref, java_lambda); - return error; - } - - int - method_invoke_java::callback_oid_put (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - int code = METHOD_CALLBACK_OID_PUT; - oid_put_request request; - request.is_compatible_java = true; - request.unpack (unpacker); - request.is_compatible_java = false; - - error = method_send_data_to_client (&thread_ref, m_client_header, code, request); - if (error != NO_ERROR) - { - return error; - } - - auto java_lambda = [&] (const cubmem::block & b) - { - return mcon_send_data_to_java (m_group->get_socket(), get_next_java_header (m_java_header), b); - }; - - error = xs_receive (&thread_ref, java_lambda); - return error; - } - - int - method_invoke_java::callback_oid_cmd (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - int code = METHOD_CALLBACK_OID_CMD; - int command; - OID oid; - unpacker.unpack_all (command, oid); - - error = method_send_data_to_client (&thread_ref, m_client_header, code, command, oid); - if (error != NO_ERROR) - { - return error; - } - - auto java_lambda = [&] (const cubmem::block & b) - { - return mcon_send_data_to_java (m_group->get_socket(), get_next_java_header (m_java_header), b); - }; - - error = xs_receive (&thread_ref, java_lambda); - return error; - } - - int - method_invoke_java::callback_collection_cmd (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - - int code = METHOD_CALLBACK_COLLECTION; - collection_cmd_request request; - request.is_compatible_java = true; - request.unpack (unpacker); - - - request.is_compatible_java = false; - - error = method_send_data_to_client (&thread_ref, m_client_header, code, request); - if (error != NO_ERROR) - { - return error; - } - - auto java_lambda = [&] (const cubmem::block & b) - { - return mcon_send_data_to_java (m_group->get_socket(), get_next_java_header (m_java_header), b); - }; - - error = xs_receive (&thread_ref, java_lambda); - return error; - } - - int - method_invoke_java::callback_make_outresult (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - - int code = METHOD_CALLBACK_MAKE_OUT_RS; - uint64_t query_id; - unpacker.unpack_all (query_id); - - error = method_send_data_to_client (&thread_ref, m_client_header, code, query_id); - if (error != NO_ERROR) - { - return error; - } - - auto get_make_outresult_info = [&] (const cubmem::block & b) - { - packing_unpacker unpacker (b.ptr, (size_t) b.dim); - - int res_code; - make_outresult_info info; - unpacker.unpack_all (res_code, info); - - const query_result_info ¤t_result_info = info.qresult_info; - query_cursor *cursor = m_group->get_cursor (current_result_info.query_id); - if (cursor) - { - cursor->change_owner (m_group->get_thread_entry ()); - return mcon_send_data_to_java (m_group->get_socket(), get_next_java_header (m_java_header), b); - } - else - { - assert (false); - return ER_FAILED; - } - }; - - error = xs_receive (&thread_ref, get_make_outresult_info); - return error; - } - - int - method_invoke_java::callback_get_generated_keys (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - int code = METHOD_CALLBACK_GET_GENERATED_KEYS; - int handler_id; - unpacker.unpack_all (handler_id); - - error = method_send_data_to_client (&thread_ref, m_client_header, code, handler_id); - if (error != NO_ERROR) - { - return error; - } - - auto java_lambda = [&] (const cubmem::block & b) - { - return mcon_send_data_to_java (m_group->get_socket(), get_next_java_header (m_java_header), b); - }; - - error = xs_receive (&thread_ref, java_lambda); - return error; - } - - int - method_invoke_java::callback_end_transaction (cubthread::entry &thread_ref, packing_unpacker &unpacker) - { - int error = NO_ERROR; - int code = METHOD_CALLBACK_END_TRANSACTION; - int command; // commit or abort - - unpacker.unpack_all (command); - error = method_send_data_to_client (&thread_ref, m_client_header, code, command); - if (error != NO_ERROR) - { - return error; - } - - auto java_lambda = [&] (const cubmem::block & b) - { - return mcon_send_data_to_java (m_group->get_socket(), get_next_java_header (m_java_header), b); - }; - - error = xs_receive (&thread_ref, java_lambda); - return error; - } - -} // namespace cubmethod diff --git a/src/method/method_query_handler.cpp b/src/method/method_query_handler.cpp index 02ffb5cd299..64764edd69f 100644 --- a/src/method/method_query_handler.cpp +++ b/src/method/method_query_handler.cpp @@ -36,6 +36,7 @@ namespace cubmethod { query_handler::query_handler (error_context &ctx, int id) : m_id (id) + , m_tid (NULL_TRANID) , m_error_ctx (ctx) , m_sql_stmt () , m_stmt_type (CUBRID_STMT_NONE) @@ -67,6 +68,7 @@ namespace cubmethod { end_qresult (); m_is_occupied = false; + } query_result::query_result () @@ -132,6 +134,18 @@ namespace cubmethod m_is_occupied = flag; } + TRANID + query_handler::get_tran_id () + { + return m_tid; + } + + void + query_handler::set_tran_id (TRANID tid) + { + m_tid = tid; + } + prepare_info & query_handler::get_prepare_info () { diff --git a/src/method/method_query_handler.hpp b/src/method/method_query_handler.hpp index 6981f7e073b..a941a796f85 100644 --- a/src/method/method_query_handler.hpp +++ b/src/method/method_query_handler.hpp @@ -100,6 +100,10 @@ namespace cubmethod int get_num_markers (); bool get_is_occupied (); void set_is_occupied (bool flag); + + TRANID get_tran_id (); + void set_tran_id (TRANID tid); + DB_SESSION *get_db_session (); DB_QUERY_TYPE *get_column_info (); @@ -148,6 +152,7 @@ namespace cubmethod private: int m_id; + TRANID m_tid; /* error */ error_context &m_error_ctx; diff --git a/src/method/method_scan.cpp b/src/method/method_scan.cpp index 80c516bc50e..965d90983c2 100644 --- a/src/method/method_scan.cpp +++ b/src/method/method_scan.cpp @@ -21,7 +21,10 @@ #include "dbtype.h" /* db_value_* */ #include "list_file.h" /* qfile_ */ #include "object_representation.h" /* OR_ */ -#include "method_runtime_context.hpp" + +#include "pl_session.hpp" +#include "pl_signature.hpp" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" @@ -39,7 +42,7 @@ namespace cubscan } int - scanner::init (cubthread::entry *thread_p, METHOD_SIG_LIST *sig_list, qfile_list_id *list_id) + scanner::init (cubthread::entry *thread_p, PL_SIGNATURE_ARRAY_TYPE *sig_array, qfile_list_id *list_id) { // check initialized if (m_thread_p != thread_p) @@ -49,7 +52,7 @@ namespace cubscan if (m_method_group == nullptr) // signature is not initialized { - m_method_group = cubmethod::get_rctx (thread_p)->create_invoke_group (thread_p, *sig_list, true); + m_method_group = new cubmethod::method_invoke_group (*sig_array); if (!m_method_group) { er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, @@ -63,7 +66,6 @@ namespace cubscan m_list_id = list_id; int arg_count = m_list_id->type_list.type_cnt; m_arg_vector.resize (arg_count); - m_arg_use_vector.resize (arg_count, false); m_arg_dom_vector.resize (arg_count); for (int i = 0; i < arg_count; i++) @@ -77,16 +79,17 @@ namespace cubscan } } - method_sig_node *sig = sig_list->method_sig; - while (sig) +#if 0 // TODO + for (int i = 0; i < sig_array->num_sigs; i++) { - for (int i = 0; i < sig->num_method_args; i++) + cubpl::pl_signature &sig = sig_array->sigs[i]; + for (int j = 0; j < sig.arg.arg_size; j++) { - int idx = sig->method_arg_pos [i]; + int idx = sig.ext.method.arg_pos[i]; m_arg_use_vector [idx] = true; } - sig = sig->next; } +#endif if (m_dbval_list == nullptr) { @@ -113,8 +116,11 @@ namespace cubscan m_method_group->reset (true); m_method_group->end (); +// TODO +#if 0 cubmethod::runtime_context *rctx = m_method_group->get_runtime_context (); rctx->pop_stack (m_thread_p, m_method_group); +#endif m_method_group = nullptr; // will be destroyed by cubmethod::runtime_context } @@ -155,11 +161,6 @@ namespace cubscan std::vector> arg_wrapper (m_arg_vector.begin (), m_arg_vector.end ()); - if (scan_code == S_SUCCESS && (error = m_method_group->prepare (arg_wrapper, m_arg_use_vector)) != NO_ERROR) - { - scan_code = S_ERROR; - } - if (scan_code == S_SUCCESS && (error = m_method_group->execute (arg_wrapper)) != NO_ERROR) { scan_code = S_ERROR; @@ -188,15 +189,17 @@ namespace cubscan m_method_group->reset (false); } + if (scan_code == S_ERROR) { - cubmethod::runtime_context *rctx = m_method_group->get_runtime_context (); - if (rctx->is_interrupted ()) - { - rctx->set_local_error_for_interrupt (); - } - else if (error != - ER_SM_INVALID_METHOD_ENV) /* FIXME: error possibly occured in builtin method, It should be handled at CAS */ +// PL_SESSION *session = m_method_group->get_session (); +// if (session->is_interrupted ()) +// { +// session->set_local_error_for_interrupt (); +// } +// else + if (error != + ER_SM_INVALID_METHOD_ENV) /* FIXME: error possibly occured in builtin method, It should be handled at CAS */ { er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_EXECUTE_ERROR, 1, m_method_group->get_error_msg ().c_str ()); } diff --git a/src/method/method_scan.hpp b/src/method/method_scan.hpp index 347bf379ea8..fd3c7a1803a 100644 --- a/src/method/method_scan.hpp +++ b/src/method/method_scan.hpp @@ -29,7 +29,7 @@ #include #include "dbtype_def.h" /* DB_VALUE */ -#include "method_def.hpp" /* method_sig_list */ + #include "method_invoke_group.hpp" /* cubmethod::method_invoke_group */ #include "object_domain.h" /* TP_DOMAIN */ #include "query_list.h" /* qfile_list_id, qfile_list_scan_id */ @@ -58,7 +58,7 @@ namespace cubscan scanner (); - int init (cubthread::entry *thread_p, method_sig_list *sig_list, qfile_list_id *list_id); + int init (cubthread::entry *thread_p, PL_SIGNATURE_ARRAY_TYPE *sig_array, qfile_list_id *list_id); void clear (bool is_final); ////////////////////////////////////////////////////////////////////////// diff --git a/src/method/method_struct_invoke.cpp b/src/method/method_struct_invoke.cpp index 23ed6c7c35f..efea0d3410d 100644 --- a/src/method/method_struct_invoke.cpp +++ b/src/method/method_struct_invoke.cpp @@ -80,7 +80,7 @@ namespace cubmethod ////////////////////////////////////////////////////////////////////////// // Common structure implementation ////////////////////////////////////////////////////////////////////////// - prepare_args::prepare_args (METHOD_GROUP_ID id, int tid, METHOD_TYPE type, + prepare_args::prepare_args (uint64_t id, int tid, METHOD_TYPE type, std::vector> &vec) : group_id (id), tran_id (tid), type (type), args (vec) { @@ -100,6 +100,7 @@ namespace cubmethod break; } case METHOD_TYPE_JAVA_SP: + case METHOD_TYPE_PLCSQL: { serializator.pack_int (tran_id); serializator.pack_int (args.size ()); @@ -142,6 +143,7 @@ namespace cubmethod break; } case METHOD_TYPE_JAVA_SP: + case METHOD_TYPE_PLCSQL: { size += serializator.get_packed_int_size (size); // tran_id size += serializator.get_packed_int_size (size); // arg count @@ -160,108 +162,4 @@ namespace cubmethod } return size; } - -////////////////////////////////////////////////////////////////////////// -// Method Builtin (C Language Method) -////////////////////////////////////////////////////////////////////////// - invoke_builtin::invoke_builtin (METHOD_GROUP_ID g_id, method_sig_node *sig) - : group_id (g_id) - , sig (sig) - { - // - } - - void - invoke_builtin::pack (cubpacking::packer &serializator) const - { - serializator.pack_bigint (group_id); - sig->pack (serializator); - } - - void - invoke_builtin::unpack (cubpacking::unpacker &deserializator) - { - deserializator.unpack_bigint (group_id); - sig = new METHOD_SIG (); - sig->unpack (deserializator); - } - - size_t - invoke_builtin::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const - { - size_t size = serializator.get_packed_bigint_size (start_offset); //group id - size += sig->get_packed_size (serializator, size); // sig - return size; - } - -////////////////////////////////////////////////////////////////////////// -// Method Java -////////////////////////////////////////////////////////////////////////// - invoke_java::invoke_java (METHOD_GROUP_ID id, int tid, method_sig_node *sig, bool tc) - : group_id (id) - , tran_id (tid) - { - signature.assign (sig->method_name); - num_args = sig->num_method_args; - - arg_pos.resize (num_args); - arg_mode.resize (num_args); - arg_type.resize (num_args); - - for (int i = 0; i < num_args; i++) - { - arg_pos[i] = sig->method_arg_pos[i]; - arg_mode[i] = sig->arg_info.arg_mode[i]; - arg_type[i] = sig->arg_info.arg_type[i]; - } - - result_type = sig->arg_info.result_type; - transaction_control = tc; - } - - void - invoke_java::pack (cubpacking::packer &serializator) const - { - serializator.pack_bigint (group_id); - serializator.pack_int (tran_id); - serializator.pack_string (signature); - serializator.pack_int (num_args); - - for (int i = 0; i < num_args; i++) - { - serializator.pack_int (arg_pos[i]); - serializator.pack_int (arg_mode[i]); - serializator.pack_int (arg_type[i]); - } - - serializator.pack_int (result_type); - serializator.pack_bool (transaction_control); - } - - void - invoke_java::unpack (cubpacking::unpacker &deserializator) - { - // TODO: unpacking is not necessary - assert (false); - } - - size_t - invoke_java::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const - { - size_t size = serializator.get_packed_bigint_size (start_offset); // group_id - size += serializator.get_packed_int_size (size); // tran_id - size += serializator.get_packed_string_size (signature, size); // signature - size += serializator.get_packed_int_size (size); // num_args - - for (int i = 0; i < num_args; i++) - { - size += serializator.get_packed_int_size (size); // arg_pos - size += serializator.get_packed_int_size (size); // arg_mode - size += serializator.get_packed_int_size (size); // arg_type - } - - size += serializator.get_packed_int_size (size); // return_type - size += serializator.get_packed_bool_size (size); // transaction_control - return size; - } } diff --git a/src/method/method_struct_invoke.hpp b/src/method/method_struct_invoke.hpp index 2bdd5a13d40..5e5c17dc493 100644 --- a/src/method/method_struct_invoke.hpp +++ b/src/method/method_struct_invoke.hpp @@ -22,9 +22,10 @@ #include #include "porting.h" -#include "method_def.hpp" + #include "mem_block.hpp" #include "packable_object.hpp" +#include "sp_constants.hpp" /* * method_struct_invoke.hpp @@ -45,7 +46,7 @@ namespace cubmethod { header () = delete; explicit header (cubpacking::unpacker &unpacker); - header (uint64_t id, int command, METHOD_REQ_ID req_id); + header (uint64_t id, int command, int req_id); void pack (cubpacking::packer &serializator) const override; void unpack (cubpacking::unpacker &deserializator) override; @@ -53,7 +54,7 @@ namespace cubmethod uint64_t id; int command; - METHOD_REQ_ID req_id; + int req_id; }; /* @@ -62,63 +63,18 @@ namespace cubmethod struct prepare_args : public cubpacking::packable_object { prepare_args () = delete; - prepare_args (METHOD_GROUP_ID id, int tran_id, METHOD_TYPE type, std::vector> &args); + prepare_args (uint64_t id, int tran_id, METHOD_TYPE type, std::vector> &args); ~prepare_args () = default; void pack (cubpacking::packer &serializator) const override; void unpack (cubpacking::unpacker &deserializator) override; size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; - METHOD_GROUP_ID group_id; + uint64_t group_id; int tran_id; METHOD_TYPE type; std::vector> &args; }; - - /* - * request data to invoke builtin(C) method - */ - struct invoke_builtin : public cubpacking::packable_object - { - invoke_builtin () = delete; - explicit invoke_builtin (cubpacking::unpacker &deserializator) - { - this->unpack (deserializator); - }; - invoke_builtin (METHOD_GROUP_ID g_id, method_sig_node *sig); - - void pack (cubpacking::packer &serializator) const override; - void unpack (cubpacking::unpacker &deserializator) override; - size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; - - METHOD_GROUP_ID group_id; - method_sig_node *sig; - }; - - /* - * request data to invoke java method - */ - struct invoke_java : public cubpacking::packable_object - { - invoke_java () = delete; - invoke_java (METHOD_GROUP_ID group_id, int tran_id, method_sig_node *sig, bool tc); - - void pack (cubpacking::packer &serializator) const override; - void unpack (cubpacking::unpacker &deserializator) override; - size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; - - METHOD_GROUP_ID group_id; - int tran_id; - - std::string signature; - int num_args; - std::vector arg_pos; - std::vector arg_mode; - std::vector arg_type; - int result_type; - - bool transaction_control; // TODO: wrap it with proper structs - }; } // namespace cubmethod #endif diff --git a/src/method/method_struct_value.cpp b/src/method/method_struct_value.cpp index 250cc7be154..97f218d2cd8 100644 --- a/src/method/method_struct_value.cpp +++ b/src/method/method_struct_value.cpp @@ -117,6 +117,7 @@ namespace cubmethod case DB_TYPE_STRING: // TODO: support unicode decomposed string { + serializator.pack_int (db_get_string_codeset (&v)); serializator.pack_c_string (db_get_string (&v), db_get_string_size (&v)); } break; @@ -330,6 +331,7 @@ namespace cubmethod case DB_TYPE_VARNCHAR: case DB_TYPE_STRING: { + size += serializator.get_packed_int_size (size); /* codeset */ size += serializator.get_packed_int_size (size); /* dummy size */ size += serializator.get_packed_c_string_size (db_get_string (value), db_get_string_size (value), size); } @@ -519,11 +521,12 @@ namespace cubmethod case DB_TYPE_VARNCHAR: case DB_TYPE_STRING: { + int codeset; cubmem::extensible_block blk { cubmem::PRIVATE_BLOCK_ALLOCATOR }; + deserializator.unpack_int (codeset); deserializator.unpack_string_to_memblock (blk); // TODO: unicode compose hanlding - #if 0 char *invalid_pos = NULL; int len = strlen (blk.get_ptr ()); @@ -559,17 +562,7 @@ namespace cubmethod } #endif db_make_string (v, blk.release_ptr ()); - - INTL_CODESET codeset; - int collation; -#if !defined (SERVER_MODE) - codeset = lang_get_client_charset (); - collation = lang_get_client_collation (); -#else - codeset = LANG_SYS_CODESET; - collation = LANG_SYS_COLLATION; -#endif - db_string_put_cs_and_collation (v, codeset, collation); + db_string_put_cs_and_collation (v, codeset, LANG_GET_BINARY_COLLATION (codeset)); v->need_clear = true; } break; diff --git a/src/method/query_method.cpp b/src/method/query_method.cpp index fb92904547c..729aa84eba6 100644 --- a/src/method/query_method.cpp +++ b/src/method/query_method.cpp @@ -43,11 +43,12 @@ #include "mem_block.hpp" /* cubmem::extensible_block */ #include "method_callback.hpp" -#include "method_def.hpp" /* method_sig_list, method_sig_node */ + #include "method_query_handler.hpp" #include "transaction_cl.h" #include "packer.hpp" /* packing_packer */ +#include "network_callback_cl.hpp" #endif #if defined (SERVER_MODE) || defined (SA_MODE) @@ -88,7 +89,7 @@ static void method_set_runtime_arguments (UINT64 id, std::vector &args static int method_prepare_arguments (packing_unpacker &unpacker); static int method_invoke_builtin (packing_unpacker &unpacker, DB_VALUE &result); -static int method_invoke_builtin_internal (DB_VALUE &result, std::vector &args, method_sig_node *meth_sig_p); +static int method_invoke_builtin_internal (DB_VALUE &result, std::vector &args, cubpl::pl_signature &sig); static int method_dispatch_internal (packing_unpacker &unpacker); @@ -124,7 +125,7 @@ method_dispatch (unsigned int rc, char *methoddata, int methoddata_size) if (error == NO_ERROR) { - cubmethod::mcon_set_connection_info (depth - 1, rc); + xs_set_conn_info (depth - 1, rc); error = method_dispatch_internal (unpacker); } @@ -146,8 +147,8 @@ method_error (unsigned int rc, int error_id) int error = NO_ERROR; tran_begin_libcas_function(); int depth = tran_get_libcas_depth (); - cubmethod::mcon_set_connection_info (depth - 1, rc); - error = cubmethod::mcon_send_data_to_server (METHOD_ERROR, error_id); + xs_set_conn_info (depth - 1, rc); + error = xs_send_queue (METHOD_ERROR, error_id); tran_end_libcas_function(); return error; } @@ -252,17 +253,19 @@ static int method_invoke_builtin (packing_unpacker &unpacker, DB_VALUE &result) { int error = NO_ERROR; + uint64_t group_id; + cubpl::pl_signature ib; + unpacker.unpack_all (group_id, ib); - cubmethod::invoke_builtin ib (unpacker); - auto search = runtime_args.find (ib.group_id); + auto search = runtime_args.find (group_id); if (search != runtime_args.end()) { std::vector &args = search->second; - error = method_invoke_builtin_internal (result, args, ib.sig); + error = method_invoke_builtin_internal (result, args, ib); if (error == NO_ERROR) { /* send a result value to server */ - error = cubmethod::mcon_send_data_to_server (METHOD_SUCCESS, result); + error = xs_send_queue (METHOD_SUCCESS, result); } } else @@ -270,7 +273,6 @@ method_invoke_builtin (packing_unpacker &unpacker, DB_VALUE &result) error = ER_GENERIC_ERROR; } - delete ib.sig; return error; } @@ -336,60 +338,49 @@ method_set_runtime_arguments (UINT64 id, std::vector &args) */ // *INDENT-OFF* int -method_invoke_builtin_internal (DB_VALUE & result, std::vector &args, method_sig_node * meth_sig_p) +method_invoke_builtin_internal (DB_VALUE & result, std::vector &args, cubpl::pl_signature &sig) // *INDENT-ON* { int error = NO_ERROR; int turn_on_auth = 1; - assert (meth_sig_p != NULL); - assert (meth_sig_p->method_type == METHOD_TYPE_CLASS_METHOD || meth_sig_p->method_type == METHOD_TYPE_INSTANCE_METHOD); - /* The first position # is for the object ID */ - int num_args = meth_sig_p->num_method_args + 1; + int num_args = sig.arg.arg_size + 1; // *INDENT-OFF* - std::vector arg_val_p (num_args + 1, NULL); /* + 1 for C method */ + std::vector arg_val_p (num_args + 1, NULL); // *INDENT-ON* for (int i = 0; i < num_args; ++i) { - int pos = meth_sig_p->method_arg_pos[i]; + int pos = sig.ext.method.arg_pos[i]; arg_val_p[i] = &args[pos]; } db_make_null (&result); - if (meth_sig_p->method_type == METHOD_TYPE_INSTANCE_METHOD || meth_sig_p->method_type == METHOD_TYPE_CLASS_METHOD) + + /* Don't call the method if the object is NULL or it has been deleted. A method call on a NULL object is + * NULL. */ + if (!DB_IS_NULL (arg_val_p[0])) { - /* Don't call the method if the object is NULL or it has been deleted. A method call on a NULL object is - * NULL. */ - if (!DB_IS_NULL (arg_val_p[0])) - { - error = db_is_any_class (db_get_object (arg_val_p[0])); - if (error == 0) - { - error = db_is_instance (db_get_object (arg_val_p[0])); - } - } - if (error == ER_HEAP_UNKNOWN_OBJECT) - { - error = NO_ERROR; - } - else if (error > 0) + error = db_is_any_class (db_get_object (arg_val_p[0])); + if (error == 0) { - /* methods must run with authorization turned on and database modifications turned off. */ - turn_on_auth = 0; - AU_ENABLE (turn_on_auth); - db_disable_modification (); - error = obj_send_array (db_get_object (arg_val_p[0]), meth_sig_p->method_name, &result, &arg_val_p[1]); - db_enable_modification (); - AU_DISABLE (turn_on_auth); + error = db_is_instance (db_get_object (arg_val_p[0])); } } - else + if (error == ER_HEAP_UNKNOWN_OBJECT) { - /* java stored procedure is not handled here anymore */ - assert (false); - error = ER_GENERIC_ERROR; + error = NO_ERROR; + } + else if (error > 0) + { + /* methods must run with authorization turned on and database modifications turned off. */ + turn_on_auth = 0; + AU_ENABLE (turn_on_auth); + db_disable_modification (); + error = obj_send_array (db_get_object (arg_val_p[0]), sig.name, &result, &arg_val_p[1]); + db_enable_modification (); + AU_DISABLE (turn_on_auth); } /* error handling */ @@ -592,6 +583,8 @@ method_fixup_vobjs (DB_VALUE *value_p) #endif #if defined (SERVER_MODE) || defined (SA_MODE) + +#if 0 /* * xmethod_invoke_fold_constants () - perform constant folding for method * return : error code @@ -626,3 +619,5 @@ int xmethod_invoke_fold_constants (THREAD_ENTRY *thread_p, const method_sig_list return error_code; } #endif + +#endif diff --git a/src/method/query_method.hpp b/src/method/query_method.hpp index 30fc2a47538..7821fd53031 100644 --- a/src/method/query_method.hpp +++ b/src/method/query_method.hpp @@ -34,7 +34,7 @@ // forward def struct method_sig_list; struct qfile_list_id; -struct method_sig_node; + #if defined(CS_MODE) extern int method_dispatch (unsigned int rc, char *methoddata, int methoddata_size); diff --git a/src/object/authenticate.c b/src/object/authenticate.c index 868fbb80f37..c84c356ba8b 100644 --- a/src/object/authenticate.c +++ b/src/object/authenticate.c @@ -38,6 +38,8 @@ #include #include +#include + #include "porting.h" #include "misc_string.h" #include "memory_alloc.h" diff --git a/src/object/authenticate.h b/src/object/authenticate.h index fc38d5602b8..f318db60fab 100644 --- a/src/object/authenticate.h +++ b/src/object/authenticate.h @@ -91,6 +91,10 @@ class print_output; #define au_check_user au_ctx ()->check_user #define au_has_user_name au_ctx ()->has_user_name +// execution rights +#define au_perform_push_user au_ctx ()->push_user +#define au_perform_pop_user au_ctx ()->pop_user + #define AU_SET_USER au_set_user // FIXME: To migrate legacy @@ -139,8 +143,8 @@ extern int au_login (const char *name, const char *password, bool ignore_dba_pri * GRANT/REVOKE OPERATIONS (authenticate_grant.cpp) */ -extern int au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option); -extern int au_revoke (MOP user, MOP class_mop, DB_AUTH type); +extern int au_grant (DB_OBJECT_TYPE obj_type, MOP user, MOP class_mop, DB_AUTH type, bool grant_option); +extern int au_revoke (DB_OBJECT_TYPE obj_type, MOP user, MOP class_mop, DB_AUTH type, MOP drop_user); #if defined (SA_MODE) extern int au_force_write_new_auth (void); @@ -208,6 +212,7 @@ extern bool au_is_server_authorized_user (DB_VALUE * owner_val); do \ { \ Au_cache.reset_authorization_caches (); \ + Au_cache.reset_user_cache (); \ } \ while (0) // @@ -216,7 +221,7 @@ extern bool au_is_server_authorized_user (DB_VALUE * owner_val); * MIGRATION OPERATIONS (authenticate_migration.cpp) */ extern int au_export_users (extract_context & ctxt, print_output & output_ctx); -extern int au_export_grants (extract_context & ctxt, print_output & output_ctx, MOP class_mop); +extern int au_export_grants (extract_context & ctxt, print_output & output_ctx, MOP class_mop, DB_OBJECT_TYPE obj_type); // /* @@ -242,6 +247,7 @@ extern void au_dump_auth (FILE * fp); // /* + * Etc * SET TYPE OPERATIONS */ extern int au_get_set (MOP obj, const char *attname, DB_SET ** set); diff --git a/src/object/authenticate_access_auth.cpp b/src/object/authenticate_access_auth.cpp index e64a38b14e0..2d104958d6e 100644 --- a/src/object/authenticate_access_auth.cpp +++ b/src/object/authenticate_access_auth.cpp @@ -32,6 +32,8 @@ #include "schema_manager.h" #include "schema_system_catalog_constants.h" +#include "jsp_cl.h" + const char *AU_TYPE_SET[] = { "SELECT", /* DB_AUTH_SELECT */ @@ -54,25 +56,24 @@ const int AU_TYPE_SET_LEN[] = strlen ("EXECUTE") /* DB_AUTH_EXECUTE */ }; -MOP au_auth_accessor::au_class_mop = nullptr; - au_auth_accessor::au_auth_accessor () : m_au_obj (nullptr) + , m_au_class_mop (nullptr) {} int au_auth_accessor::create_new_auth () { - if (au_class_mop == nullptr) + if (m_au_class_mop == nullptr) { - au_class_mop = sm_find_class (CT_CLASSAUTH_NAME); - if (au_class_mop == NULL) + m_au_class_mop = sm_find_class (CT_CLASSAUTH_NAME); + if (m_au_class_mop == nullptr) { er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_AU_MISSING_CLASS, 1, CT_CLASSAUTH_NAME); } } - m_au_obj = db_create_internal (au_class_mop); + m_au_obj = db_create_internal (m_au_class_mop); if (m_au_obj == NULL) { assert (er_errid () != NO_ERROR); @@ -81,13 +82,16 @@ au_auth_accessor::create_new_auth () } int -au_auth_accessor::set_new_auth (MOP au_obj, MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, bool grant_option) +au_auth_accessor::set_new_auth (DB_OBJECT_TYPE obj_type, MOP au_obj, MOP grantor, MOP user, MOP obj_mop, + DB_AUTH auth_type, bool grant_option) { - DB_VALUE value, class_name_val; - MOP db_class = nullptr, db_class_inst = nullptr; + DB_VALUE value; + MOP db_class = nullptr, inst_mop = nullptr; DB_AUTH type; int i; int error = NO_ERROR; + char unique_name[DB_MAX_IDENTIFIER_LENGTH + 1]; + unique_name[0] = '\0'; m_au_obj = au_obj; if (m_au_obj == nullptr) @@ -101,24 +105,34 @@ au_auth_accessor::set_new_auth (MOP au_obj, MOP grantor, MOP user, MOP class_mop db_make_object (&value, user); obj_set (m_au_obj, AU_AUTH_ATTR_GRANTEE, &value); - db_class = sm_find_class (CT_CLASS_NAME); - if (db_class == NULL) + if (obj_type == DB_OBJECT_CLASS) { - assert (er_errid () != NO_ERROR); - return er_errid (); + inst_mop = obj_mop; } - - db_make_string (&class_name_val, sm_get_ch_name (class_mop)); - db_class_inst = obj_find_unique (db_class, "unique_name", &class_name_val, AU_FETCH_READ); - if (db_class_inst == NULL) + else { - assert (er_errid () != NO_ERROR); - pr_clear_value (&class_name_val); - return er_errid (); + // TODO: CBRD-24912 + if (jsp_get_unique_name (obj_mop, unique_name, DB_MAX_IDENTIFIER_LENGTH) == NULL) + { + assert (er_errid () != NO_ERROR); + pr_clear_value (&value); + return er_errid (); + } + + inst_mop = jsp_find_stored_procedure (unique_name, DB_AUTH_NONE); + if (inst_mop == NULL) + { + assert (er_errid () != NO_ERROR); + pr_clear_value (&value); + return er_errid (); + } } - db_make_object (&value, db_class_inst); - obj_set (m_au_obj, "class_of", &value); + db_make_int (&value, (int) obj_type); + obj_set (m_au_obj, "object_type", &value); + + db_make_object (&value, inst_mop); + obj_set (m_au_obj, "object_of", &value); for (type = DB_AUTH_SELECT, i = 0; type != auth_type; type = (DB_AUTH) (type << 1), i++); @@ -128,12 +142,12 @@ au_auth_accessor::set_new_auth (MOP au_obj, MOP grantor, MOP user, MOP class_mop db_make_int (&value, (int) grant_option); obj_set (m_au_obj, "is_grantable", &value); - pr_clear_value (&class_name_val); + pr_clear_value (&value); return NO_ERROR; } int -au_auth_accessor::get_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type) +au_auth_accessor::get_new_auth (DB_OBJECT_TYPE obj_type, MOP grantor, MOP user, MOP obj_mop, DB_AUTH auth_type) { int error = NO_ERROR, save, i = 0; DB_VALUE val[COUNT_FOR_VARIABLES]; @@ -141,11 +155,15 @@ au_auth_accessor::get_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH au DB_QUERY_RESULT *result = NULL; DB_SESSION *session = NULL; STATEMENT_ID stmt_id; - const char *class_name; + const char *name; const char *sql_query = "SELECT [au].object FROM [" CT_CLASSAUTH_NAME "] [au]" " WHERE [au].[grantee].[name] = ? AND [au].[grantor].[name] = ?" - " AND [au].[class_of].[unique_name] = ? AND [au].[auth_type] = ?"; // TODO: static + " AND [au].[object_of] = (%s) AND [au].[auth_type] = ?"; + char obj_fetch_query[256]; + const char *class_unique_name = NULL; + char sp_unique_name[DB_MAX_IDENTIFIER_LENGTH + 1]; + char error_msg[ERR_MSG_SIZE]; for (i = 0; i < COUNT_FOR_VARIABLES; i++) { @@ -157,54 +175,107 @@ au_auth_accessor::get_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH au /* Disable the checking for internal authorization object access */ AU_DISABLE (save); + switch (obj_type) + { + case DB_OBJECT_CLASS: + class_unique_name = sm_get_ch_name (obj_mop); + if (class_unique_name == NULL) + { + assert (false); + error = ER_UNEXPECTED; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Cannot get class name of mop."); + goto exit; + } + + sprintf (obj_fetch_query, sql_query, "SELECT [cl].[class_of] FROM " CT_CLASS_NAME "[cl] WHERE [unique_name] = ?"); + break; + case DB_OBJECT_PROCEDURE: + sp_unique_name[0] = '\0'; + if (jsp_get_unique_name (obj_mop, sp_unique_name, DB_MAX_IDENTIFIER_LENGTH) == NULL) + { + assert (false); + error = ER_UNEXPECTED; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Cannot get stored procedure name of mop."); + goto exit; + } + + sprintf (obj_fetch_query, sql_query, "SELECT [sp] FROM " CT_STORED_PROC_NAME "[sp] WHERE [unique_name] = ?"); + break; + default: + assert (false); + error = ER_UNEXPECTED; + error_msg[0] = '\0'; + snprintf (error_msg, sizeof (error_msg) - 1, "unknown database object id: %d.", obj_type); + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, error_msg); + goto exit; + } + + session = db_open_buffer_local (obj_fetch_query); + if (session == NULL) + { + assert (er_errid () != NO_ERROR); + goto exit; + } + + error = db_set_system_generated_statement (session); + if (error != NO_ERROR) + { + goto release; + } + + stmt_id = db_compile_statement_local (session); + if (stmt_id != 1) + { + assert (er_errid () != NO_ERROR); + goto release; + } + /* Prepare DB_VALUEs for host variables */ error = obj_get (user, "name", &val[INDEX_FOR_GRANTEE_NAME]); if (error != NO_ERROR) { - goto exit; + goto release; } else if (!DB_IS_STRING (&val[INDEX_FOR_GRANTEE_NAME]) || DB_IS_NULL (&val[INDEX_FOR_GRANTEE_NAME]) || db_get_string (&val[INDEX_FOR_GRANTEE_NAME]) == NULL) { er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_AU_MISSING_OR_INVALID_USER, 0); - goto exit; + goto release; } error = obj_get (grantor, "name", &val[INDEX_FOR_GRANTOR_NAME]); if (error != NO_ERROR) { - goto exit; + goto release; } else if (!DB_IS_STRING (&val[INDEX_FOR_GRANTOR_NAME]) || DB_IS_NULL (&val[INDEX_FOR_GRANTOR_NAME]) || db_get_string (&val[INDEX_FOR_GRANTOR_NAME]) == NULL) { er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_AU_MISSING_OR_INVALID_USER, 0); - goto exit; + goto release; } - class_name = db_get_class_name (class_mop); - if (class_name == NULL) + switch (obj_type) { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SM_INVALID_CLASS, 0); - goto exit; + case DB_OBJECT_CLASS: + db_make_string (&val[INDEX_FOR_OBJECT_NAME], class_unique_name); + break; + case DB_OBJECT_PROCEDURE: + db_make_string (&val[INDEX_FOR_OBJECT_NAME], sp_unique_name); + break; + default: + assert (false); + error = ER_FAILED; + goto release; } - db_make_string (&val[INDEX_FOR_CLASS_NAME], class_name); i = 0; for (DB_AUTH type = DB_AUTH_SELECT; type != auth_type; type = (DB_AUTH) (type << 1)) { i++; } - db_make_string (&val[INDEX_FOR_AUTH_TYPE], AU_TYPE_SET[i]); - session = db_open_buffer (sql_query); - if (session == NULL) - { - assert (er_errid () != NO_ERROR); - goto release; - } - error = db_push_values (session, COUNT_FOR_VARIABLES, val); if (error != NO_ERROR) { @@ -212,13 +283,6 @@ au_auth_accessor::get_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH au goto release; } - stmt_id = db_compile_statement (session); - if (stmt_id != 1) - { - assert (er_errid () != NO_ERROR); - goto release; - } - error = db_execute_statement_local (session, stmt_id, &result); /* The error value is row count if it's not negative value. */ @@ -282,14 +346,15 @@ au_auth_accessor::get_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH au } int -au_auth_accessor::insert_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option) +au_auth_accessor::insert_auth (DB_OBJECT_TYPE obj_type, MOP grantor, MOP user, MOP obj_mop, DB_AUTH auth_type, + int grant_option) { int error = NO_ERROR; for (int index = DB_AUTH_EXECUTE; index; index >>= 1) { if (auth_type & index) { - error = set_new_auth (NULL, grantor, user, class_mop, (DB_AUTH) index, + error = set_new_auth (obj_type, NULL, grantor, user, obj_mop, (DB_AUTH) index, ((grant_option & index) ? true : false)); if (error != NO_ERROR) { @@ -302,14 +367,15 @@ au_auth_accessor::insert_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH aut } int -au_auth_accessor::update_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option) +au_auth_accessor::update_auth (DB_OBJECT_TYPE obj_type, MOP grantor, MOP user, MOP obj_mop, DB_AUTH auth_type, + int grant_option) { int error = NO_ERROR; for (int index = DB_AUTH_EXECUTE; index; index >>= 1) { if (auth_type & index) { - error = get_new_auth (grantor, user, class_mop, (DB_AUTH) index); + error = get_new_auth (obj_type, grantor, user, obj_mop, (DB_AUTH) index); if (error != NO_ERROR) { return error; @@ -323,7 +389,7 @@ au_auth_accessor::update_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH aut return error; } - error = set_new_auth (m_au_obj, grantor, user, class_mop, (DB_AUTH) index, + error = set_new_auth (obj_type, m_au_obj, grantor, user, obj_mop, (DB_AUTH) index, ((grant_option & index) ? true : false)); if (error != NO_ERROR) { @@ -336,14 +402,14 @@ au_auth_accessor::update_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH aut } int -au_auth_accessor::delete_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type) +au_auth_accessor::delete_auth (DB_OBJECT_TYPE obj_type, MOP grantor, MOP user, MOP obj_mop, DB_AUTH auth_type) { int error = NO_ERROR; for (int index = DB_AUTH_EXECUTE; index; index >>= 1) { if (auth_type & index) { - error = get_new_auth (grantor, user, class_mop, (DB_AUTH) index); + error = get_new_auth (obj_type, grantor, user, obj_mop, (DB_AUTH) index); if (error != NO_ERROR) { return error; @@ -440,32 +506,45 @@ au_delete_auth_of_dropping_user (MOP user) return error; } - /* - * au_delete_auth_of_dropping_table - delete _db_auth records refers to the given table. + * au_delete_auth_of_dropping_database_object - delete _db_auth records refers to the given database object. * return: error code - * class_name(in): the class name to be dropped + * obj_type(in): the object type + * name(in): the object name to be dropped */ int -au_delete_auth_of_dropping_table (const char *class_name) +au_delete_auth_of_dropping_database_object (DB_OBJECT_TYPE obj_type, const char *name) { int error = NO_ERROR, save; - const char *sql_query = - "DELETE FROM [" CT_CLASSAUTH_NAME "] [au]" " WHERE [au].[class_of] IN" " (SELECT [cl] FROM " CT_CLASS_NAME - " [cl] WHERE [unique_name] = ?);"; + const char *sql_query = "DELETE FROM [" CT_CLASSAUTH_NAME "] [au]" " WHERE [au].[object_of] IN (%s);"; DB_VALUE val; DB_QUERY_RESULT *result = NULL; DB_SESSION *session = NULL; int stmt_id; + char obj_fetch_query[256]; db_make_null (&val); /* Disable the checking for internal authorization object access */ AU_DISABLE (save); - assert (class_name != NULL); + assert (name != NULL); - session = db_open_buffer_local (sql_query); + switch (obj_type) + { + case DB_OBJECT_CLASS: + sprintf (obj_fetch_query, sql_query, "SELECT [cl].[class_of] FROM " CT_CLASS_NAME "[cl] WHERE [unique_name] = ?"); + break; + case DB_OBJECT_PROCEDURE: + sprintf (obj_fetch_query, sql_query, "SELECT [sp] FROM " CT_STORED_PROC_NAME "[sp] WHERE [unique_name] = ?"); + break; + default: + assert (false); + error = ER_FAILED; + goto exit; + } + + session = db_open_buffer_local (obj_fetch_query); if (session == NULL) { ASSERT_ERROR_AND_SET (error); @@ -485,7 +564,7 @@ au_delete_auth_of_dropping_table (const char *class_name) goto release; } - db_make_string (&val, class_name); + db_make_string (&val, name); error = db_push_values (session, 1, &val); if (error != NO_ERROR) { @@ -584,3 +663,485 @@ au_delete_authorizartion_of_dropping_user (MOP user) return error; } + +/* + * au_object_revoke_all_privileges - drop a class, virtual class and procedure, or when changing the owner, all privileges are revoked. + * return: error code + * obj_mop(in): a class/stored procedure object + * grantor_mop(in): a class/stored procedure owner + */ +int +au_object_revoke_all_privileges (DB_OBJECT_TYPE obj_type, MOP grantor_mop, const char *unique_name) +{ + int error = NO_ERROR, save, len, i = 0; + const char *auth; + DB_AUTH db_auth; + MOP grantee_mop, object_of_mop; + DB_VALUE val[2]; + DB_VALUE grantee_value, object_of_value, auth_type_value; + DB_QUERY_RESULT *result = NULL; + DB_SESSION *session = NULL; + int stmt_id; + int row_count = -1; + char obj_fetch_query[256]; + const char *sql_query = + "SELECT [au].grantee, [au].object_of, [au].auth_type FROM [" CT_CLASSAUTH_NAME "] [au]" + " WHERE [au].[grantor].[name] = ? AND [au].[object_of] = (%s);"; + + assert (grantor_mop != NULL && unique_name != NULL); + + for (i = 0; i < 2; i++) + { + db_make_null (&val[i]); + } + + db_make_null (&grantee_value); + db_make_null (&object_of_value); + db_make_null (&auth_type_value); + + /* Disable the checking for internal authorization object access */ + AU_DISABLE (save); + + switch (obj_type) + { + case DB_OBJECT_CLASS: + sprintf (obj_fetch_query, sql_query, "SELECT [cl].[class_of] FROM " CT_CLASS_NAME "[cl] WHERE [unique_name] = ?"); + break; + case DB_OBJECT_PROCEDURE: + sprintf (obj_fetch_query, sql_query, "SELECT [sp] FROM " CT_STORED_PROC_NAME "[sp] WHERE [unique_name] = ?"); + break; + default: + assert (false); + error = ER_FAILED; + goto exit; + } + + session = db_open_buffer_local (obj_fetch_query); + if (session == NULL) + { + ASSERT_ERROR_AND_SET (error); + goto exit; + } + + error = db_set_system_generated_statement (session); + if (error != NO_ERROR) + { + goto release; + } + + stmt_id = db_compile_statement_local (session); + if (stmt_id < 0) + { + ASSERT_ERROR_AND_SET (error); + goto release; + } + + /* Prepare DB_VALUEs for host variables */ + error = obj_get (grantor_mop, "name", &val[0]); + if (error != NO_ERROR) + { + goto release; + } + else if (!DB_IS_STRING (&val[0]) || DB_IS_NULL (&val[0]) + || db_get_string (&val[0]) == NULL) + { + error = ER_AU_MISSING_OR_INVALID_USER; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0); + goto release; + } + + db_make_string (&val[1], unique_name); + + error = db_push_values (session, 2, val); + if (error != NO_ERROR) + { + assert (er_errid () != NO_ERROR); + goto release; + } + + error = db_execute_statement_local (session, stmt_id, &result); + + /* The error value is row count if it's not negative value. */ + if (error == 0) + { + row_count = error; + goto release; + } + else if (error < 0) + { + assert (er_errid () != NO_ERROR); + goto release; + } + + row_count = error; + error = NO_ERROR; + + while (db_query_next_tuple (result) == DB_CURSOR_SUCCESS) + { + if (db_query_get_tuple_value (result, 0, &grantee_value) == NO_ERROR) + { + grantee_mop = NULL; + if (!DB_IS_NULL (&grantee_value)) + { + grantee_mop = db_get_object (&grantee_value); + } + else + { + goto release; + } + } + + if (db_query_get_tuple_value (result, 1, &object_of_value) == NO_ERROR) + { + object_of_mop = NULL; + if (!DB_IS_NULL (&object_of_value)) + { + object_of_mop = db_get_object (&object_of_value); + } + else + { + goto release; + } + } + + if (db_query_get_tuple_value (result, 2, &auth_type_value) == NO_ERROR) + { + auth = NULL; + if (!DB_IS_NULL (&auth_type_value)) + { + auth = db_get_char (&auth_type_value, &len); + + switch (auth[0]) + { + case 'A': + db_auth = DB_AUTH_ALTER; + break; + + case 'D': + db_auth = DB_AUTH_DELETE; + break; + + case 'E': + db_auth = DB_AUTH_EXECUTE; + break; + + case 'I': + if (auth[2] == 'D') + { + db_auth = DB_AUTH_INDEX; + } + else if (auth[2] == 'S') + { + db_auth = DB_AUTH_INSERT; + } + else + { + db_auth = DB_AUTH_NONE; + } + break; + + case 'S': + db_auth = DB_AUTH_SELECT; + break; + + case 'U': + db_auth = DB_AUTH_UPDATE; + break; + + default: + db_auth = DB_AUTH_NONE; + break; + } + } + else + { + goto release; + } + } + + assert (grantee_mop != NULL); + assert (object_of_mop != NULL); + assert (db_auth != DB_AUTH_NONE); + + error = au_revoke (obj_type, grantee_mop, object_of_mop, db_auth, NULL); + if (error != NO_ERROR) + { + goto release; + } + } + +release: + if (result != NULL) + { + db_query_end (result); + } + if (session != NULL) + { + db_close_session (session); + } + +exit: + AU_ENABLE (save); + + db_value_clear (&grantee_value); + db_value_clear (&object_of_value); + db_value_clear (&auth_type_value); + + for (i = 0; i < 2; i++) + { + db_value_clear (&val[i]); + } + + if (row_count < 0 && er_errid () == NO_ERROR && (grantee_mop == NULL || object_of_mop == NULL + || auth == NULL || db_auth == DB_AUTH_NONE)) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0); + error = ER_GENERIC_ERROR; + } + + return (error); +} + +/* + * au_user_revoke_all_privileges - when a user is deleted, all of their privileges are revoked. + * return: error code + * user_mop(in): a user object + */ +int +au_user_revoke_all_privileges (MOP user_mop) +{ + int error = NO_ERROR, save, len; + int object_type; + DB_OBJECT_TYPE obj_type; + const char *auth; + DB_AUTH db_auth; + MOP grantee_mop, obj_mop; + DB_VALUE name; + DB_VALUE grantee_value, object_type_value, object_of_value, auth_type_value; + DB_QUERY_RESULT *result = NULL; + DB_SESSION *session = NULL; + int stmt_id; + int row_count = -1; + const char *sql_query = + "SELECT [au].grantee, [au].object_type, [au].object_of, [au].auth_type FROM [" CT_CLASSAUTH_NAME "] [au]" + " WHERE [au].[grantor].[name] = ?"; + + assert (user_mop != NULL); + + + db_make_null (&name); + db_make_null (&grantee_value); + db_make_null (&object_type_value); + db_make_null (&object_of_value); + db_make_null (&auth_type_value); + + /* Disable the checking for internal authorization object access */ + AU_DISABLE (save); + + session = db_open_buffer_local (sql_query); + if (session == NULL) + { + ASSERT_ERROR_AND_SET (error); + goto exit; + } + + error = db_set_system_generated_statement (session); + if (error != NO_ERROR) + { + goto release; + } + + stmt_id = db_compile_statement_local (session); + if (stmt_id < 0) + { + ASSERT_ERROR_AND_SET (error); + goto release; + } + + /* Prepare DB_VALUEs for host variables */ + error = obj_get (user_mop, "name", &name); + if (error != NO_ERROR) + { + goto release; + } + else if (!DB_IS_STRING (&name) || DB_IS_NULL (&name) + || db_get_string (&name) == NULL) + { + error = ER_AU_MISSING_OR_INVALID_USER; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0); + goto release; + } + + error = db_push_values (session, 1, &name); + if (error != NO_ERROR) + { + assert (er_errid () != NO_ERROR); + goto release; + } + + error = db_execute_statement_local (session, stmt_id, &result); + + /* The error value is row count if it's not negative value. */ + if (error == 0) + { + row_count = error; + goto release; + } + else if (error < 0) + { + assert (er_errid () != NO_ERROR); + goto release; + } + + row_count = error; + error = NO_ERROR; + + while (db_query_next_tuple (result) == DB_CURSOR_SUCCESS) + { + if (db_query_get_tuple_value (result, 0, &grantee_value) == NO_ERROR) + { + grantee_mop = NULL; + if (!DB_IS_NULL (&grantee_value)) + { + grantee_mop = db_get_object (&grantee_value); + } + else + { + goto release; + } + } + + if (db_query_get_tuple_value (result, 1, &object_type_value) == NO_ERROR) + { + object_type = 0; + if (!DB_IS_NULL (&object_type_value)) + { + object_type = db_get_int (&object_type_value); + switch (object_type) + { + case 0: + obj_type = DB_OBJECT_CLASS; + break; + + case 5: + obj_type = DB_OBJECT_PROCEDURE; + break; + + default: + assert (object_type == 0 || object_type == 5); + goto release; + } + } + else + { + goto release; + } + } + + if (db_query_get_tuple_value (result, 2, &object_of_value) == NO_ERROR) + { + obj_mop = NULL; + if (!DB_IS_NULL (&object_of_value)) + { + obj_mop = db_get_object (&object_of_value); + } + else + { + goto release; + } + } + + if (db_query_get_tuple_value (result, 3, &auth_type_value) == NO_ERROR) + { + auth = NULL; + if (!DB_IS_NULL (&auth_type_value)) + { + auth = db_get_char (&auth_type_value, &len); + + switch (auth[0]) + { + case 'A': + db_auth = DB_AUTH_ALTER; + break; + + case 'D': + db_auth = DB_AUTH_DELETE; + break; + + case 'E': + db_auth = DB_AUTH_EXECUTE; + break; + + case 'I': + if (auth[2] == 'D') + { + db_auth = DB_AUTH_INDEX; + } + else if (auth[2] == 'S') + { + db_auth = DB_AUTH_INSERT; + } + else + { + db_auth = DB_AUTH_NONE; + } + break; + + case 'S': + db_auth = DB_AUTH_SELECT; + break; + + case 'U': + db_auth = DB_AUTH_UPDATE; + break; + + default: + db_auth = DB_AUTH_NONE; + break; + } + } + else + { + goto release; + } + } + + assert (grantee_mop != NULL); + assert (obj_mop != NULL); + assert (db_auth != DB_AUTH_NONE); + + error = au_revoke (obj_type, grantee_mop, obj_mop, db_auth, user_mop); + if (error != NO_ERROR) + { + goto release; + } + } + +release: + if (result != NULL) + { + db_query_end (result); + } + if (session != NULL) + { + db_close_session (session); + } + +exit: + AU_ENABLE (save); + + db_value_clear (&grantee_value); + db_value_clear (&object_type_value); + db_value_clear (&object_of_value); + db_value_clear (&auth_type_value); + db_value_clear (&name); + + if (row_count < 0 && er_errid () == NO_ERROR && (grantee_mop == NULL || obj_mop == NULL || auth == NULL + || db_auth == DB_AUTH_NONE || (object_type != 0 && object_type != 5))) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0); + error = ER_GENERIC_ERROR; + } + + return (error); +} \ No newline at end of file diff --git a/src/object/authenticate_access_auth.hpp b/src/object/authenticate_access_auth.hpp index 8be9573b842..297e2483bed 100644 --- a/src/object/authenticate_access_auth.hpp +++ b/src/object/authenticate_access_auth.hpp @@ -46,7 +46,7 @@ class au_auth_accessor { private: // TODO: thread safe? - static MOP au_class_mop; + MOP m_au_class_mop; MOP m_au_obj; @@ -54,26 +54,27 @@ class au_auth_accessor { INDEX_FOR_GRANTEE_NAME = 0, INDEX_FOR_GRANTOR_NAME = 1, - INDEX_FOR_CLASS_NAME = 2, + INDEX_FOR_OBJECT_NAME = 2, INDEX_FOR_AUTH_TYPE = 3, /* Total count for the above */ COUNT_FOR_VARIABLES }; int create_new_auth (); - int set_new_auth (MOP au_object, MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, bool grant_option); - int get_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type); + int set_new_auth (DB_OBJECT_TYPE obj_type, MOP au_object, MOP grantor, MOP user, MOP obj_mop, DB_AUTH auth_type, + bool grant_option); + int get_new_auth (DB_OBJECT_TYPE obj_type, MOP grantor, MOP user, MOP obj_mop, DB_AUTH auth_type); public: explicit au_auth_accessor (); - int insert_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option); - int update_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option); - int delete_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type); + int insert_auth (DB_OBJECT_TYPE obj_type, MOP grantor, MOP user, MOP obj_mop, DB_AUTH auth_type, int grant_option); + int update_auth (DB_OBJECT_TYPE obj_type, MOP grantor, MOP user, MOP obj_mop, DB_AUTH auth_type, int grant_option); + int delete_auth (DB_OBJECT_TYPE obj_type, MOP grantor, MOP user, MOP obj_mop, DB_AUTH auth_type); - static MOP get_auth_class_mop () + MOP get_auth_class_mop () { - return au_class_mop; + return m_au_class_mop; } MOP get_auth_object () @@ -93,6 +94,16 @@ extern int au_delete_auth_of_dropping_user (MOP user); extern int au_delete_authorizartion_of_dropping_user (MOP user); // delete _db_auth records refers to the given table -extern int au_delete_auth_of_dropping_table (const char *class_name); +extern int au_delete_auth_of_dropping_database_object (DB_OBJECT_TYPE obj_type, const char *name); + +/* +* drop a class, virtual class and procedure, or when changing the owner, all privileges are revoked. +*/ +extern int au_object_revoke_all_privileges (DB_OBJECT_TYPE obj_type, MOP grantor_mop, const char *unique_name); + +/* +* when a user is deleted, all of their privileges are revoked. +*/ +extern int au_user_revoke_all_privileges (MOP user_mop); #endif // _authenticate_access_auth_HPP_ \ No newline at end of file diff --git a/src/object/authenticate_access_user.cpp b/src/object/authenticate_access_user.cpp index 0cf0740d679..22d838b4d11 100644 --- a/src/object/authenticate_access_user.cpp +++ b/src/object/authenticate_access_user.cpp @@ -73,6 +73,7 @@ au_find_user (const char *user_name) char *upper_case_name; size_t upper_case_name_size; DB_VALUE user_name_string; + AU_USER_CACHE *user_cache = nullptr; if (user_name == NULL) { @@ -96,9 +97,6 @@ au_find_user (const char *user_name) } } - /* disable checking of internal authorization object access */ - AU_DISABLE (save); - user = NULL; upper_case_name_size = intl_identifier_upper_string_size (user_name); @@ -110,6 +108,17 @@ au_find_user (const char *user_name) } intl_identifier_upper (user_name, upper_case_name); + user_cache = Au_cache.find_user_cache_by_name (upper_case_name); + if (user_cache) + { + user = user_cache->user; + assert (user != NULL); + return user; + } + + /* disable checking of internal authorization object access */ + AU_DISABLE (save); + /* * first try to find the user id by index. This is faster than * a query, and will not get blocked out as a server request @@ -174,6 +183,11 @@ au_find_user (const char *user_name) } } + if (user) + { + (void) Au_cache.make_user_cache (user_name, user, false); + } + exit: AU_ENABLE (save); @@ -636,6 +650,12 @@ au_add_user (const char *name, int *exists) } AU_ENABLE (save); } + + if (user != NULL) + { + (void) Au_cache.make_user_cache (name, user, false); + } + return (user); } @@ -1350,6 +1370,13 @@ au_drop_user (MOP user) } } + /* before deleting an user, all permissions are revoked. */ + error = au_user_revoke_all_privileges (user); + if (error != NO_ERROR) + { + goto error; + } + error = au_delete_auth_of_dropping_user (user); if (error != NO_ERROR) { @@ -1370,7 +1397,7 @@ au_drop_user (MOP user) error = obj_delete (user); if (error == NO_ERROR) { - Au_cache.remove_user_cache_references (user); + Au_cache.remove_user_cache (user); } error: diff --git a/src/object/authenticate_cache.cpp b/src/object/authenticate_cache.cpp index dcbb614808e..8369626bec4 100644 --- a/src/object/authenticate_cache.cpp +++ b/src/object/authenticate_cache.cpp @@ -28,7 +28,22 @@ #include "schema_manager.h" #include "set_object.h" -static void free_user_cache (AU_USER_CACHE *u); +au_class_cache::au_class_cache (int depth) +{ + next = NULL; + class_ = NULL; + data = new unsigned int[depth]; + std::fill_n (data, depth, AU_CACHE_INVALID); +} + +au_class_cache::~au_class_cache () +{ + if (data) + { + delete [] data; + data = nullptr; + } +} authenticate_cache::authenticate_cache () { @@ -51,7 +66,6 @@ authenticate_cache::init (void) cache_index = -1; } - /* * flush_caches - Called during au_final(). Free the authorization cache * structures and initialize the global variables @@ -75,6 +89,7 @@ authenticate_cache::flush (void) nextu = u->next; free_user_cache (u); } + user_name_cache.clear (); /* clear the associated globals */ init (); @@ -281,6 +296,7 @@ authenticate_cache::free_authorization_cache (void *cache) { AU_CLASS_CACHE *c, *prev; + prev = NULL; if (cache != NULL) { for (c = class_caches, prev = NULL; c != NULL && c != cache; c = c->next) @@ -297,12 +313,11 @@ authenticate_cache::free_authorization_cache (void *cache) { prev->next = c->next; } + free_class_cache ((AU_CLASS_CACHE *) cache); } - free_class_cache ((AU_CLASS_CACHE *) cache); } } - /* * AUTHORIZATION CACHES */ @@ -325,20 +340,12 @@ authenticate_cache::make_class_cache (int depth) } else { - size = sizeof (AU_CLASS_CACHE) + ((depth - 1) * sizeof (unsigned int)); - new_class_cache = (AU_CLASS_CACHE *) malloc (size); + new_class_cache = new (std::nothrow) AU_CLASS_CACHE (depth); if (new_class_cache == NULL) { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size); + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (AU_CLASS_CACHE)); return NULL; } - - new_class_cache->next = NULL; - new_class_cache->class_ = NULL; - for (i = 0; i < depth; i++) - { - new_class_cache->data[i] = AU_CACHE_INVALID; - } } return new_class_cache; @@ -354,7 +361,7 @@ authenticate_cache::free_class_cache (AU_CLASS_CACHE *cache) { if (cache != NULL) { - free_and_init (cache); + delete cache; } } @@ -472,72 +479,122 @@ authenticate_cache::extend_class_caches (int *index) } /* - * au_find_user_cache_index - This determines the cache index for the given - * user. - * return: error code - * user(in): user object - * index(out): returned user index - * check_it(in): + * make_user_cache - This creates a new user cache and appends it to the user cache list + * return: user cache + * name(in): user name + * user(in): user MOP * - * Note: If the user has never been added to the authorization cache, - * we reserve a new index for the user. Reserving the user index may - * result in growing all the existing class caches. - * This is the primary work function for AU_SET_USER() and it should - * be fast. */ -int -authenticate_cache::find_user_cache_index (DB_OBJECT *user, int *index, int check_it) +AU_USER_CACHE * +authenticate_cache::make_user_cache (const char *name, DB_OBJECT *user, bool sanity_check) { - int error = NO_ERROR; - AU_USER_CACHE *u, *new_user_cache; - DB_OBJECT *class_mop; + AU_USER_CACHE *new_user_cache = nullptr; + assert (name != nullptr); + assert (user != nullptr); - for (u = user_cache; u != NULL && !ws_is_same_object (u->user, user); u = u->next) - ; - - if (u != NULL) - { - *index = u->index; - } - else + if (sanity_check) { /* - * User wasn't in the cache, add it and extend the existing class - * caches. First do a little sanity check just to make sure this - * is a user object. - */ - if (check_it) + * User wasn't in the cache, add it and extend the existing class + * caches. First do a little sanity check just to make sure this + * is a user object. + */ + DB_OBJECT *class_mop = sm_get_class (user); + if (class_mop == NULL) { - class_mop = sm_get_class (user); - if (class_mop == NULL) - { - assert (er_errid () != NO_ERROR); - return er_errid (); - } - else if (class_mop != Au_user_class) - { - error = ER_AU_CORRUPTED; /* need a better error */ - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0); - return er_errid (); - } + assert (er_errid () != NO_ERROR); + return NULL; } + else if (class_mop != Au_user_class) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_AU_CORRUPTED, 0); /* need a better error */ + return NULL; + } + } + + std::string upper_case_name (name); + std::transform (upper_case_name.begin(), upper_case_name.end(), upper_case_name.begin(), ::toupper); + + if ((new_user_cache = find_user_cache_by_name (upper_case_name.c_str ())) != nullptr) + { + return new_user_cache; + } + + new_user_cache = new AU_USER_CACHE; + if (new_user_cache != nullptr) + { + new_user_cache->next = user_cache; + user_cache = new_user_cache; + + new_user_cache->name = upper_case_name; + new_user_cache->user = user; + new_user_cache->index = -1; + + user_name_cache.insert (std::pair (upper_case_name, new_user_cache)); + } + + return new_user_cache; +} + +/* + * find_user_cache_by_name - This determines the cache for the given user name. + * return: user cache + * name(in): user name + * + */ +AU_USER_CACHE * +authenticate_cache::find_user_cache_by_name (const char *name) +{ + if (name == nullptr) + { + return nullptr; + } + + AU_USER_CACHE *user_cache = nullptr; + + const auto &it = user_name_cache.find (name); + if (it != user_name_cache.end()) + { + user_cache = it->second; + } + + return user_cache; +} + +/* + * find_user_cache_by_mop - This determines the cache for the given user MOP. + * return: user cache + * user(in): user mop + * + */ +AU_USER_CACHE * +authenticate_cache::find_user_cache_by_mop (DB_OBJECT *user) +{ + AU_USER_CACHE *u; + + for (u = user_cache; u != NULL && !ws_is_same_object (u->user, user); u = u->next) + ; + + return u; +} - new_user_cache = (AU_USER_CACHE *) malloc (sizeof (AU_USER_CACHE)); - if (new_user_cache != NULL) +int +authenticate_cache::get_user_cache_index (AU_USER_CACHE *cache, int *index) +{ + int error = NO_ERROR; + + if (cache->index == -1) + { + error = extend_class_caches (index); + if (error == NO_ERROR) { - if ((error = extend_class_caches (index))) - { - free_and_init (new_user_cache); - } - else - { - new_user_cache->next = user_cache; - user_cache = new_user_cache; - new_user_cache->user = user; - new_user_cache->index = *index; - } + cache->index = *index; } } + else + { + *index = cache->index; + } return error; } @@ -552,12 +609,18 @@ authenticate_cache::free_user_cache (AU_USER_CACHE *u) { if (u != NULL) { + u->next = NULL; u->user = NULL; /* clear GC roots */ - free_and_init (u); + + if (!u->name.empty ()) + { + user_name_cache.erase (u->name); + } + + delete u; } } - /* * reset_cache_for_user_and_class - This is called whenever a grant or revoke * operation is performed. It resets the @@ -590,7 +653,14 @@ authenticate_cache::reset_cache_for_user_and_class (SM_CLASS *sm_class) */ for (u = user_cache; u != NULL; u = u->next) { - c->data[u->index] = AU_CACHE_INVALID; + // NOTE: u->index is initalized as -1 + // This means that the user is cached in a context that is independent of the class, + // for example, obtaining the user object in the execution context of another database object, + // such as the owner's right of procedure or a user management method. + if (u->index >= 0) + { + c->data[u->index] = AU_CACHE_INVALID; + } } } } @@ -626,30 +696,57 @@ authenticate_cache::reset_authorization_caches (void) } /* - * remove_user_cache_reference - This is called when a user object is deleted. + * remove_user_cache - This is called when a user object is deleted. * return: none * user(in): user object * - * Note: If there is an authorization cache entry for this user, we NULL - * the user pointer so it will no longer be used. We could to in - * and restructure all the caches to remove the deleted user but user - * deletion isn't that common. Just leave an unused entry in the - * cache array. */ void -authenticate_cache::remove_user_cache_references (MOP user) +authenticate_cache::remove_user_cache (MOP user) { - AU_USER_CACHE *u; + AU_USER_CACHE *u, *prevu, *nextu; - for (u = user_cache; u != NULL; u = u->next) + prevu = NULL; + for (u = user_cache; u != NULL; u = nextu) { + nextu = u->next; if (ws_is_same_object (u->user, user)) { - u->user = NULL; + if (prevu == NULL) + { + user_cache = nextu; + } + else + { + prevu->next = nextu; + } + free_user_cache (u); + break; + } + else + { + prevu = u; } } } +/* + * reset_user_cache - This is called when a user object is invalidated. + * return: none + */ +void +authenticate_cache::reset_user_cache (void) +{ + AU_USER_CACHE *u = user_cache; + while (u != NULL) + { + AU_USER_CACHE *nextu = u->next; + free_user_cache (u); + u = nextu; + } + user_cache = NULL; +} + /* * au_print_cache() - * return: none diff --git a/src/object/authenticate_cache.hpp b/src/object/authenticate_cache.hpp index a0900b5339b..17405217b2f 100644 --- a/src/object/authenticate_cache.hpp +++ b/src/object/authenticate_cache.hpp @@ -26,6 +26,9 @@ #include "class_object.h" /* SM_CLASS */ +#include +#include + /* Invalid cache is identified when the high bit is on. */ #define AU_CACHE_INVALID 0x80000000 @@ -49,7 +52,11 @@ struct au_class_cache struct au_class_cache *next; SM_CLASS *class_; - unsigned int data[1]; + unsigned int *data; + + au_class_cache () = delete; + au_class_cache (int depth); + ~au_class_cache (); }; /* @@ -65,8 +72,11 @@ struct au_user_cache { struct au_user_cache *next; + std::string name; DB_OBJECT *user; int index; + + au_user_cache() = default; }; /* @@ -84,6 +94,15 @@ class authenticate_cache */ AU_USER_CACHE *user_cache; + /* + * Au_user_name_cache + * + * The map of user name to user cache + */ + using user_name_cache_t = std::unordered_map; + + user_name_cache_t user_name_cache; + /* * Au_class_caches * @@ -132,12 +151,18 @@ class authenticate_cache unsigned int *get_cache_bits (SM_CLASS *sm_class); void free_authorization_cache (void *cache); - int find_user_cache_index (DB_OBJECT *user, int *index, int check_it); + + AU_USER_CACHE *make_user_cache (const char *name, DB_OBJECT *user, bool sanity_check); + AU_USER_CACHE *find_user_cache_by_name (const char *name); + AU_USER_CACHE *find_user_cache_by_mop (DB_OBJECT *user); + + int get_user_cache_index (AU_USER_CACHE *cache, int *index); void reset_cache_for_user_and_class (SM_CLASS *sm_class); void reset_authorization_caches (void); - void remove_user_cache_references (MOP user); + void remove_user_cache (MOP user); + void reset_user_cache (void); void print_cache (int cache, FILE *fp); // for debugging @@ -147,6 +172,7 @@ class authenticate_cache void free_class_cache (AU_CLASS_CACHE *cache); AU_CLASS_CACHE *install_class_cache (SM_CLASS *sm_class); int extend_class_caches (int *index); + void free_user_cache (AU_USER_CACHE *u); }; diff --git a/src/object/authenticate_constants.h b/src/object/authenticate_constants.h index 21bb4029b59..a65d2204a0b 100644 --- a/src/object/authenticate_constants.h +++ b/src/object/authenticate_constants.h @@ -71,16 +71,7 @@ #define MSGCAT_AUTH_AUTH_TITLE 15 #define MSGCAT_AUTH_USER_DIRECT_GROUPS 16 -enum AU_OBJECT -{ - AU_OBJECT_CLASS, /* TABLE, VIEW (_db_class) */ - AU_OBJECT_TRIGGER, /* TRIGGER (_db_trigger) */ - AU_OBJECT_SERIAL, /* SERIAL (db_serial) */ - AU_OBJECT_SERVER, /* SERVER (db_server) */ - AU_OBJECT_SYNONYM, /* SYNONYM (_db_synonym) */ - AU_OBJECT_PROCEDURE /* PROCEDURE, FUNCTION (_db_stored_procedure) */ -}; - +typedef DB_OBJECT_TYPE AU_OBJECT; /* * Mask to extract only the authorization bits from a cache. This can also diff --git a/src/object/authenticate_context.cpp b/src/object/authenticate_context.cpp index 95bcb2be322..de5a9868204 100644 --- a/src/object/authenticate_context.cpp +++ b/src/object/authenticate_context.cpp @@ -293,6 +293,7 @@ authenticate_context::install (void) { MOP root_cls = NULL, user_cls = NULL, pass_cls = NULL, auth_cls = NULL, old_cls = NULL; SM_TEMPLATE *def; + AU_USER_CACHE *user_cache; int exists, save, index; AU_DISABLE (save); @@ -490,10 +491,17 @@ authenticate_context::install (void) } /* establish the DBA as the current user */ - if (caches.find_user_cache_index (dba_user, &index, 0) != NO_ERROR) + user_cache = caches.find_user_cache_by_mop (dba_user); + if (user_cache == NULL) + { + user_cache = caches.make_user_cache (AU_DBA_USER_NAME, dba_user, false); + } + + if (caches.get_user_cache_index (user_cache, &index) != NO_ERROR) { goto exit_on_error; } + current_user = dba_user; Au_cache.set_cache_index (index); @@ -516,11 +524,11 @@ authenticate_context::install (void) * grant browser access to the authorization objects * note that the password class cannot be read by anyone except the DBA */ - au_grant (public_user, root_cls, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false); - au_grant (public_user, old_cls, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false); - au_grant (public_user, user_cls, AU_SELECT, false); - au_grant (public_user, user_cls, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false); - au_grant (public_user, auth_cls, AU_SELECT, false); + au_grant (DB_OBJECT_CLASS, public_user, root_cls, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false); + au_grant (DB_OBJECT_CLASS, public_user, old_cls, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false); + au_grant (DB_OBJECT_CLASS, public_user, user_cls, AU_SELECT, false); + au_grant (DB_OBJECT_CLASS, public_user, user_cls, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false); + au_grant (DB_OBJECT_CLASS, public_user, auth_cls, AU_SELECT, false); au_add_method_check_authorization (); @@ -711,26 +719,41 @@ authenticate_context::set_user (MOP newuser) { int error = NO_ERROR; int index; + AU_USER_CACHE *user_cache; if (newuser != NULL && !ws_is_same_object (newuser, current_user)) { - if (! (error = caches.find_user_cache_index (newuser, &index, 1))) + user_cache = caches.find_user_cache_by_mop (newuser); + if (!user_cache) { + const char *user_name = au_get_user_name (newuser); + user_cache = caches.make_user_cache (user_name, newuser, false); + } - current_user = newuser; - caches.set_cache_index (index); + if (user_cache) + { + if (caches.get_user_cache_index (user_cache, &index) == NO_ERROR) + { + current_user = newuser; + caches.set_cache_index (index); - /* - * it is important that we don't call sm_bump_local_schema_version() here - * because this function is called during the compilation of vclasses - */ + /* + * it is important that we don't call sm_bump_local_schema_version() here + * because this function is called during the compilation of vclasses + */ - /* - * Entry-level SQL specifies that the schema name is the same as - * the current user authorization name. In any case, this is - * the place to set the current schema since the user just changed. - */ - error = sc_set_current_schema (current_user); + /* + * Entry-level SQL specifies that the schema name is the same as + * the current user authorization name. In any case, this is + * the place to set the current schema since the user just changed. + */ + error = sc_set_current_schema (current_user); + } + } + else + { + // you can guarantee that user cache is already created in au_find_user () + assert (false); } } return (error); @@ -914,6 +937,40 @@ authenticate_context::get_user_class_name (void) return AU_USER_CLASS_NAME; } +int +authenticate_context::push_user (MOP user) +{ + MOP save_user = Au_user; + if (AU_SET_USER (user) == NO_ERROR) + { + user_stack.push (save_user); + return NO_ERROR; + } + else + { + return ER_FAILED; + } +} + +int +authenticate_context::pop_user (void) +{ + if (user_stack.size () == 0) + { + return ER_FAILED; + } + + if (AU_SET_USER (user_stack.top ()) == NO_ERROR) + { + user_stack.pop (); + return NO_ERROR; + } + else + { + return ER_FAILED; + } +} + // // STATIC FUNCTIONS // @@ -949,7 +1006,7 @@ au_add_method_check_authorization (void) smt_assign_argument_domain (def, "check_authorization", true, NULL, 2, "integer", (DB_DOMAIN *) 0); sm_update_class (def, NULL); - au_grant (Au_public_user, auth, AU_EXECUTE, false); + au_grant (DB_OBJECT_CLASS, Au_public_user, auth, AU_EXECUTE, false); AU_ENABLE (save); return NO_ERROR; diff --git a/src/object/authenticate_context.hpp b/src/object/authenticate_context.hpp index 8c77dd8a55c..f3d0791cd70 100644 --- a/src/object/authenticate_context.hpp +++ b/src/object/authenticate_context.hpp @@ -24,6 +24,8 @@ #ifndef _AUTHENTICATE_CONTEXT_HPP_ #define _AUTHENTICATE_CONTEXT_HPP_ +#include + #include "porting.h" #include "dbtype_def.h" @@ -113,6 +115,14 @@ class EXPORT_IMPORT authenticate_context * system authorizations. */ MOP current_user; + + /* + * Au_user_stack + * + * This manages the MOP stack to track execution rights of stored procedures. + */ + std::stack user_stack; + /* * Au_user_name, Au_user_password * @@ -161,6 +171,10 @@ class EXPORT_IMPORT authenticate_context int check_user (void); bool has_user_name (void); + // execution rights + int push_user (MOP user); + int pop_user (); + // getters MOP get_public_user (void); MOP get_dba_user (void); diff --git a/src/object/authenticate_grant.cpp b/src/object/authenticate_grant.cpp index e961370c7b6..99f6e46922d 100644 --- a/src/object/authenticate_grant.cpp +++ b/src/object/authenticate_grant.cpp @@ -37,16 +37,28 @@ #include "object_accessor.h" /* obj_inst_lock () */ #include "object_primitive.h" +#include "msgcat_glossary.hpp" + +#include "jsp_cl.h" #if defined(SA_MODE) extern bool catcls_Enable; #endif /* SA_MODE */ +static int au_grant_class (MOP user, MOP class_mop, DB_AUTH type, bool grant_option); +static int au_grant_procedure (MOP user, MOP obj_mop, DB_AUTH type, bool grant_option); + +static int au_revoke_class (MOP user, MOP class_mop, DB_AUTH type, MOP drop_user); +static int au_revoke_procedure (MOP user, MOP obj_mop, DB_AUTH type, MOP drop_user); + static int check_grant_option (MOP classop, SM_CLASS *sm_class, DB_AUTH type); static int collect_class_grants (MOP class_mop, DB_AUTH type, MOP revoked_auth, int revoked_grant_index, AU_GRANT **return_grants); -static int propagate_revoke (AU_GRANT *grant_list, MOP owner, DB_AUTH mask); -static int au_propagate_del_new_auth (AU_GRANT *glist, DB_AUTH mask); +static int propagate_revoke (DB_OBJECT_TYPE obj_type, AU_GRANT *grant_list, MOP owner, DB_AUTH mask); +static int au_propagate_del_new_auth (DB_OBJECT_TYPE obj_type, AU_GRANT *glist, DB_AUTH mask); + +static int au_compare_grantor_and_return (MOP *grantor, MOP obj_mop, DB_AUTH type, MOP login_user, MOP class_owner, + MOP drop_user); /* * GRANT STRUCTURE OPERATION @@ -55,7 +67,7 @@ static void free_grant_list (AU_GRANT *grants); static void map_grant_list (AU_GRANT *grants, MOP grantor); static int find_grant_entry (DB_SET *grants, MOP class_mop, MOP grantor); -static int add_grant_entry (DB_SET *grants, MOP class_mop, MOP grantor); +static int add_grant_entry (DB_SET *grants, DB_OBJECT_TYPE obj_type, MOP obj_mop, MOP grantor); static void drop_grant_entry (DB_SET *grants, int index); static void print_grant_entry (DB_SET *grants, int grant_index, FILE *fp); @@ -65,15 +77,46 @@ static void print_grant_entry (DB_SET *grants, int grant_index, FILE *fp); /* * au_grant - This is the primary interface function for granting authorization - * on classes. + * on database objects. * return: error code + * obj_type(in): database object type to be granted * user(in): user receiving the grant * class_mop(in): class being authorized * type(in): type of authorization * grant_option(in): non-zero if grant option is also being given */ int -au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) +au_grant (DB_OBJECT_TYPE obj_type, MOP user, MOP class_mop, DB_AUTH type, bool grant_option) +{ + int error = NO_ERROR; + switch (obj_type) + { + case DB_OBJECT_CLASS: + error = au_grant_class (user, class_mop, type, grant_option); + break; + + case DB_OBJECT_PROCEDURE: + error = au_grant_procedure (user, class_mop, type, grant_option); + break; + default: + error = ER_FAILED; + assert (false); + break; + } + return error; +} + +/* + * au_grant_class - This is the primary interface function for granting authorization + * on classes. + * return: error code + * user(in): user receiving the grant + * class_mop(in): class being authorized + * type(in): type of authorization + * grant_option(in): non-zero if grant option is also being given + */ +static int +au_grant_class (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) { int error = NO_ERROR; MOP auth; @@ -83,6 +126,7 @@ au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) SM_CLASS *classobj; int is_partition = DB_NOT_PARTITIONED_CLASS, i, savepoint_grant = 0; MOP *sub_partitions = NULL; + MOP grantor = NULL; error = sm_partitioned_class_type (class_mop, &is_partition, NULL, &sub_partitions); if (error != NO_ERROR) @@ -101,7 +145,7 @@ au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) savepoint_grant = 1; for (i = 0; sub_partitions[i]; i++) { - error = au_grant (user, sub_partitions[i], type, grant_option); + error = au_grant_class (user, sub_partitions[i], type, grant_option); if (error != NO_ERROR) { break; @@ -116,24 +160,50 @@ au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) } AU_DISABLE (save); - if (ws_is_same_object (user, Au_user)) - { - /* - * Treat grant to self condition as a success only. Although this - * statement is a no-op, it is not an indication of no-success. - * The "privileges" are indeed already granted to self. - * Note: Revoke from self is an error, because this cannot be done. - */ - } - else if ((error = au_fetch_class_force (class_mop, &classobj, AU_FETCH_READ)) == NO_ERROR) + if ((error = au_fetch_class_force (class_mop, &classobj, AU_FETCH_READ)) == NO_ERROR) { - if (ws_is_same_object (classobj->owner, user)) + if (ws_is_same_object (user, Au_user)) + { + /* + * Treat grant to self condition as a success only. Although this + * statement is a no-op, it is not an indication of no-success. + * The "privileges" are indeed already granted to self. + * Note: Revoke from self is an error, because this cannot be done. + * Additionally, two conditions have been added: + * 1) No-op is disabled if the user does not have access to the CLASS (excluding the owner) + * Example : + * CALL LOGIN('u1', '') ON CLASS db_user; + * GRANT SELECT ON dba.tbl TO u1; + * Result : ERROR: SELECT authorization failure + * 2) No-op is disabled if the user has access to the CLASS but does not have the WITH GRANT OPTION (excluding the owner). + * Example : + * CALL LOGIN(class db_user, 'dba', ''); + * GRANT SELECT ON dba.tbl TO u1; + * CALL LOGIN('u1', '') ON CLASS db_user; + * GRANT SELECT ON dba.tbl TO u1; + * Result : ERROR: No GRANT option. + */ + + error = check_grant_option (class_mop, classobj, type); + if (error != NO_ERROR) + { + return (error); + } + } + else if (ws_is_same_object (classobj->owner, user)) { error = ER_AU_CANT_GRANT_OWNER; - er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_CLASS)); } - else if ((error = check_grant_option (class_mop, classobj, type)) == NO_ERROR) + else if ((error = au_compare_grantor_and_return (&grantor, class_mop, type, Au_user, classobj->owner, + NULL)) != NO_ERROR) { + return (error); + } + else + { + assert (grantor != NULL); + if (au_get_object (user, "authorization", &auth) != NO_ERROR) { error = ER_AU_ACCESS_ERROR; @@ -147,7 +217,7 @@ au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) } else if ((error = obj_inst_lock (auth, 1)) == NO_ERROR && (error = get_grants (auth, &grants, 1)) == NO_ERROR) { - gindex = find_grant_entry (grants, class_mop, Au_user); + gindex = find_grant_entry (grants, class_mop, grantor); if (gindex == -1) { current = AU_NO_AUTHORIZATION; @@ -180,15 +250,15 @@ au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) if (ins_bits) { error = - accessor.insert_auth (Au_user, user, class_mop, ins_bits, + accessor.insert_auth (DB_OBJECT_CLASS, grantor, user, class_mop, ins_bits, (grant_option) ? ins_bits : DB_AUTH_NONE); } upd_bits = (DB_AUTH) (~ins_bits & (int) type); if ((error == NO_ERROR) && upd_bits) { error = - accessor.update_auth (Au_user, user, class_mop, upd_bits, - (grant_option) ? upd_bits : DB_AUTH_NONE); + accessor.update_auth (DB_OBJECT_CLASS, grantor, user, class_mop, upd_bits, + (grant_option || (current & (type << AU_GRANT_SHIFT))) ? upd_bits : DB_AUTH_NONE); } } @@ -209,7 +279,7 @@ au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) if (gindex == -1) { /* There is no grant entry, add a new one. */ - gindex = add_grant_entry (grants, class_mop, Au_user); + gindex = add_grant_entry (grants, DB_OBJECT_CLASS, class_mop, grantor); } set_put_element (grants, GRANT_ENTRY_CACHE (gindex), &value); set_free (grants); @@ -242,6 +312,161 @@ au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) return (error); } +static int +au_grant_procedure (MOP user, MOP obj_mop, DB_AUTH type, bool grant_option) +{ + int error = NO_ERROR; + DB_VALUE value; + MOP auth; + DB_SET *grants; + int current, save = 0, gindex; + MOP grantor = NULL; + + assert (type == AU_EXECUTE); + + AU_DISABLE (save); + MOP sp_owner = jsp_get_owner (obj_mop); + + /* + * The WITH GRANT OPTION is not yet supported for stored procedures. + * Therefore, only the DBA, member of the DBA group, and the owner can grant privileges. + */ + if (!au_is_dba_group_member (Au_user) && !au_is_user_group_member (sp_owner, Au_user)) + { + error = ER_AU_OWNER_ONLY_GRANT_PRIVILEGE; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "EXECUTE"); + return (error); + } + + if (ws_is_same_object (user, Au_user)) + { + /* + * Treat grant to self condition as a success only. Although this + * statement is a no-op, it is not an indication of no-success. + * The "privileges" are indeed already granted to self. + * Note: Revoke from self is an error, because this cannot be done. + */ + } + else + { + if (ws_is_same_object (sp_owner, user)) + { + error = ER_AU_CANT_GRANT_OWNER; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_PROCEDURE)); + } + else if ((error = au_compare_grantor_and_return (&grantor, obj_mop, type, Au_user, sp_owner, NULL)) != NO_ERROR) + { + return (error); + } + else + { + assert (grantor != NULL); + + if (au_get_object (user, "authorization", &auth) != NO_ERROR) + { + error = ER_AU_ACCESS_ERROR; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 2, AU_USER_CLASS_NAME, "authorization"); + } + /* lock authorization for write & mark dirty */ + else if (au_fetch_instance (auth, NULL, AU_FETCH_UPDATE, LC_FETCH_MVCC_VERSION, AU_UPDATE) != NO_ERROR) + { + error = ER_AU_CANT_UPDATE; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0); + } + else if ((error = obj_inst_lock (auth, 1)) == NO_ERROR && (error = get_grants (auth, &grants, 1)) == NO_ERROR) + { + gindex = find_grant_entry (grants, obj_mop, grantor); + if (gindex == -1) + { + current = AU_NO_AUTHORIZATION; + } + else + { + /* already granted, get current cache */ + error = set_get_element (grants, GRANT_ENTRY_CACHE (gindex), &value); + if (error != NO_ERROR) + { + set_free (grants); + AU_ENABLE (save); + return (error); + } + current = db_get_int (&value); + } + +#if defined(SA_MODE) + if (catcls_Enable == true) +#endif /* SA_MODE */ + { + au_auth_accessor accessor; + DB_AUTH ins_bits, upd_bits; + + ins_bits = (DB_AUTH) ((~current & AU_TYPE_MASK) & (int) type); + if (ins_bits) + { + error = + accessor.insert_auth (DB_OBJECT_PROCEDURE, grantor, user, obj_mop, AU_EXECUTE, DB_AUTH_NONE); + } + + upd_bits = (DB_AUTH) (~ins_bits & (int) type); + if ((error == NO_ERROR) && upd_bits) + { + error = + accessor.update_auth (DB_OBJECT_PROCEDURE, grantor, user, obj_mop, AU_EXECUTE, DB_AUTH_NONE); + } + } + + /* Fail to insert/update, never change the grant entry set. */ + if (error != NO_ERROR) + { + set_free (grants); + goto end; + } + + current |= (int) type; + /* TODO: no grant option for procedure */ + /* + if (grant_option) + { + current |= ((int) type << AU_GRANT_SHIFT); + } + */ + + db_make_int (&value, current); + if (gindex == -1) + { + /* There is no grant entry, add a new one. */ + gindex = add_grant_entry (grants, DB_OBJECT_PROCEDURE, obj_mop, grantor); + } + set_put_element (grants, GRANT_ENTRY_CACHE (gindex), &value); + set_free (grants); + + /* Fail to insert/update, never change the grant entry set. */ + if (error != NO_ERROR) + { + set_free (grants); + goto end; + } + + /* + * clear the cache for this user/class pair to make sure we + * recalculate it the next time it is referenced + */ + //reset_cache_for_user_and_class (classobj); + + /* + * Make sure any cached parse trees are rebuild. This proabably + * isn't necessary for GRANT, only REVOKE. + */ + sm_bump_local_schema_version (); + } + } + } + +end: + AU_ENABLE (save); + return (error); +} + /* * au_revoke - This is the primary interface function for * revoking authorization @@ -249,6 +474,7 @@ au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) * user(in): user being revoked * class_mop(in): class being revoked * type(in): type of authorization being revoked + * drop_user(in) : used when executing the drop user statement * * Note: The authorization of the given type on the given class is removed * from the authorization info stored with the given user. If this @@ -259,7 +485,45 @@ au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option) * TODO : LP64 */ int -au_revoke (MOP user, MOP class_mop, DB_AUTH type) +au_revoke (DB_OBJECT_TYPE obj_type, MOP user, MOP obj_mop, DB_AUTH type, MOP drop_user) +{ + int error = NO_ERROR; + switch (obj_type) + { + case DB_OBJECT_CLASS: + error = au_revoke_class (user, obj_mop, type, drop_user); + break; + + case DB_OBJECT_PROCEDURE: + error = au_revoke_procedure (user, obj_mop, type, drop_user); + break; + default: + error = ER_FAILED; + assert (false); + break; + } + return error; +} + +/* + * au_revoke_class - This is the primary interface function for + * revoking authorization + * return: error code + * user(in): user being revoked + * class_mop(in): class being revoked + * type(in): type of authorization being revoked + * drop_user(in) : used when executing the drop user statement + * + * Note: The authorization of the given type on the given class is removed + * from the authorization info stored with the given user. If this + * user has the grant option for this type and has granted authorization + * to other users, the revoke will be recursively propagated to all + * affected users. + * + * TODO : LP64 + */ +static int +au_revoke_class (MOP user, MOP class_mop, DB_AUTH type, MOP drop_user) { int error; MOP auth; @@ -270,6 +534,7 @@ au_revoke (MOP user, MOP class_mop, DB_AUTH type) SM_CLASS *classobj; int is_partition = DB_NOT_PARTITIONED_CLASS, i = 0, savepoint_revoke = 0; MOP *sub_partitions = NULL; + MOP grantor = NULL; error = sm_partitioned_class_type (class_mop, &is_partition, NULL, &sub_partitions); if (error != NO_ERROR) @@ -288,7 +553,7 @@ au_revoke (MOP user, MOP class_mop, DB_AUTH type) for (i = 0; sub_partitions[i]; i++) { - error = au_revoke (user, sub_partitions[i], type); + error = au_revoke_class (user, sub_partitions[i], type, drop_user); if (error != NO_ERROR) { break; @@ -316,11 +581,11 @@ au_revoke (MOP user, MOP class_mop, DB_AUTH type) if (ws_is_same_object (classobj->owner, user)) { error = ER_AU_CANT_REVOKE_OWNER; - er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_CLASS)); goto fail_end; } - error = check_grant_option (class_mop, classobj, type); + error = au_compare_grantor_and_return (&grantor, class_mop, type, Au_user, classobj->owner, drop_user); if (error != NO_ERROR) { goto fail_end; @@ -340,7 +605,7 @@ au_revoke (MOP user, MOP class_mop, DB_AUTH type) } else if ((error = obj_inst_lock (auth, 1)) == NO_ERROR && (error = get_grants (auth, &grants, 1)) == NO_ERROR) { - gindex = find_grant_entry (grants, class_mop, Au_user); + gindex = find_grant_entry (grants, class_mop, grantor); if (gindex == -1) { error = ER_AU_GRANT_NOT_FOUND; @@ -350,7 +615,7 @@ au_revoke (MOP user, MOP class_mop, DB_AUTH type) else { /* get current cache bits */ - error = set_get_element (grants, gindex + 2, &cache_element); + error = set_get_element (grants, GRANT_ENTRY_CACHE (gindex), &cache_element); if (error != NO_ERROR) { set_free (grants); @@ -394,7 +659,7 @@ au_revoke (MOP user, MOP class_mop, DB_AUTH type) mask = (int) ~ (type | (type << AU_GRANT_SHIFT)); /* propagate the revoke to the affected classes */ - if ((error = propagate_revoke (grant_list, classobj->owner, (DB_AUTH) mask)) == NO_ERROR) + if ((error = propagate_revoke (DB_OBJECT_CLASS, grant_list, classobj->owner, (DB_AUTH) mask)) == NO_ERROR) { /* @@ -405,7 +670,7 @@ au_revoke (MOP user, MOP class_mop, DB_AUTH type) if (current) { db_make_int (&cache_element, current); - set_put_element (grants, gindex + 2, &cache_element); + set_put_element (grants, GRANT_ENTRY_CACHE (gindex), &cache_element); } else { @@ -424,7 +689,7 @@ au_revoke (MOP user, MOP class_mop, DB_AUTH type) { #endif /* SA_MODE */ au_auth_accessor accessor; - error = accessor.delete_auth (Au_user, user, class_mop, type); + error = accessor.delete_auth (DB_OBJECT_CLASS, grantor, user, class_mop, type); #if defined(SA_MODE) } #endif /* SA_MODE */ @@ -458,6 +723,193 @@ au_revoke (MOP user, MOP class_mop, DB_AUTH type) return (error); } +static int +au_revoke_procedure (MOP user, MOP obj_mop, DB_AUTH type, MOP drop_user) +{ + int error = NO_ERROR; + DB_SET *grants = NULL; + MOP auth; + int save = 0, current = 0, gindex, mask, savepoint_revoke = 0; + AU_GRANT *grant_list; + DB_VALUE cache_element; + MOP sp_owner; + MOP grantor = NULL; + + AU_DISABLE (save); + if (ws_is_same_object (user, Au_user)) + { + error = ER_AU_CANT_REVOKE_SELF; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + goto fail_end; + } + + sp_owner = jsp_get_owner (obj_mop); + if (sp_owner == NULL) + { + error = ER_FAILED; + goto fail_end; + } + + if (error == NO_ERROR) + { + if (ws_is_same_object (sp_owner, user)) + { + error = ER_AU_CANT_REVOKE_OWNER; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_PROCEDURE)); + goto fail_end; + } + + /* GRANT OPTION is not supported yet for stored procedure + error = check_grant_option (class_mop, obj_mop, type); + if (error != NO_ERROR) + { + goto fail_end; + } + */ + /* + * The WITH GRANT OPTION is not yet supported for stored procedures. + * Therefore, if the user is not the dba group or owner, the same error as grant/revoke_class is output. + * example: + * call login(class db_user,'public',''); + * REVOKE EXECUTE ON PROCEDURE u1.hello FROM u2; + */ + if (!au_is_dba_group_member (Au_user) && !au_is_user_group_member (sp_owner, Au_user)) + { + error = ER_AU_EXECUTE_FAILURE; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + goto fail_end; + } + + error = au_compare_grantor_and_return (&grantor, obj_mop, type, Au_user, sp_owner, drop_user); + if (error != NO_ERROR) + { + goto fail_end; + } + + if (au_get_object (user, "authorization", &auth) != NO_ERROR) + { + error = ER_AU_ACCESS_ERROR; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 2, AU_USER_CLASS_NAME, "authorization"); + goto fail_end; + } + else if (au_fetch_instance (auth, NULL, AU_FETCH_UPDATE, LC_FETCH_MVCC_VERSION, AU_UPDATE) != NO_ERROR) + { + error = ER_AU_CANT_UPDATE; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0); + goto fail_end; + } + else if ((error = obj_inst_lock (auth, 1)) == NO_ERROR && (error = get_grants (auth, &grants, 1)) == NO_ERROR) + { + gindex = find_grant_entry (grants, obj_mop, grantor); + if (gindex == -1) + { + error = ER_AU_GRANT_NOT_FOUND; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + goto fail_end; + } + else + { + /* get current cache bits */ + error = set_get_element (grants, GRANT_ENTRY_CACHE (gindex), &cache_element); + if (error != NO_ERROR) + { + set_free (grants); + AU_ENABLE (save); + return (error); + } + current = db_get_int (&cache_element); + + /* + * If all the bits are set, assume we wan't to + * revoke everything previously granted, makes it a bit + * easier but muddies the semantics too much ? + */ + if (type == DB_AUTH_ALL) + { + type = (DB_AUTH) (current & AU_TYPE_MASK); + } + + /* + * this test could be more sophisticated, right now, + * if there are any valid grants that fit in + * the specified bit mask, the operation will proceed, + * we could make sure that every bit in the supplied + * mask is also present in the cache and if not abort + * the whole thing + */ + + if ((current & (int) type) == 0) + { + error = ER_AU_GRANT_NOT_FOUND; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + } + else if ((error = collect_class_grants (obj_mop, type, auth, gindex, &grant_list)) == NO_ERROR) + { + /* calculate the mask to turn off the grant */ + mask = (int) ~ (type | (type << AU_GRANT_SHIFT)); + + /* propagate the revoke to the affected classes */ + if ((error = propagate_revoke (DB_OBJECT_PROCEDURE, grant_list, sp_owner, (DB_AUTH) mask)) == NO_ERROR) + { + + /* + * finally, update the local grant for the + * original object + */ + current &= mask; + if (current) + { + db_make_int (&cache_element, current); + set_put_element (grants, GRANT_ENTRY_CACHE (gindex), &cache_element); + } + else + { + /* no remaining grants, remove it from the grant set */ + drop_grant_entry (grants, gindex); + } + /* + * clear the cache for this user/class pair + * to make sure we recalculate it the next time + * it is referenced + */ + // TODO: CBRD-24912 + // reset_cache_for_user_and_procedure (obj_mop); + +#if defined(SA_MODE) + if (catcls_Enable == true) + { +#endif /* SA_MODE */ + au_auth_accessor accessor; + error = accessor.delete_auth (DB_OBJECT_PROCEDURE, grantor, user, obj_mop, type); +#if defined(SA_MODE) + } +#endif /* SA_MODE */ + /* + * Make sure that we don't keep any parse trees + * around that rely on obsolete authorization. + * This may not be necessary. + */ + sm_bump_local_schema_version (); + } + free_grant_list (grant_list); + } + } + } + } + +fail_end: + if (grants != NULL) + { + set_free (grants); + } + if (savepoint_revoke && error != NO_ERROR && error != ER_LK_UNILATERALLY_ABORTED) + { + (void) tran_abort_upto_system_savepoint (UNIQUE_PARTITION_SAVEPOINT_REVOKE); + } + AU_ENABLE (save); + return (error); +} + /* * check_grant_option - Checks to see if a class has the grant option for * a particular authorization type. @@ -701,23 +1153,27 @@ map_grant_list (AU_GRANT *grants, MOP grantor) } /* - * add_grant_entry - This adds a grant on a class from a particular user to + * add_grant_entry - This adds a grant on a database object from a particular user to * a sequence of grant elemetns. * It returns the index of the new grant element. * return: sequence index to new grant entry * grants(in): grant sequence to extend - * class_mop(in): class being granted + * db_obj_type(in): database object type + * obj_mop(in): database object being granted * grantor(in): user doing the granting */ static int -add_grant_entry (DB_SET *grants, MOP class_mop, MOP grantor) +add_grant_entry (DB_SET *grants, DB_OBJECT_TYPE obj_type, MOP obj_mop, MOP grantor) { DB_VALUE value; int index; index = set_size (grants); - db_make_object (&value, class_mop); + db_make_int (&value, (int) obj_type); + set_put_element (grants, GRANT_ENTRY_TYPE (index), &value); + + db_make_object (&value, obj_mop); set_put_element (grants, GRANT_ENTRY_CLASS (index), &value); db_make_object (&value, grantor); @@ -754,17 +1210,17 @@ drop_grant_entry (DB_SET *grants, int index) /* * find_grant_entry - This searches a sequence of grant elements looking for - * a grant from a particular user on a particular class. + * a grant from a particular user on a particular database object. * return: sequence index to grant entry * grants(in): sequence of grant information - * class_mop(in): class to look for + * obj_mop(in): database object to look for * grantor(in): user who made the grant * * Note: It returns the index into the sequence where the grant information * is found. If the grant was not found it returns -1. */ static int -find_grant_entry (DB_SET *grants, MOP class_mop, MOP grantor) +find_grant_entry (DB_SET *grants, MOP obj_mop, MOP grantor) { DB_VALUE element; int i, gsize, position; @@ -774,7 +1230,7 @@ find_grant_entry (DB_SET *grants, MOP class_mop, MOP grantor) for (i = 0; i < gsize && position == -1; i += GRANT_ENTRY_LENGTH) { set_get_element (grants, GRANT_ENTRY_CLASS (i), &element); - if (db_get_object (&element) == class_mop) + if (db_get_object (&element) == obj_mop) { set_get_element (grants, GRANT_ENTRY_SOURCE (i), &element); if (ws_is_same_object (db_get_object (&element), grantor)) @@ -798,10 +1254,29 @@ static void print_grant_entry (DB_SET *grants, int grant_index, FILE *fp) { DB_VALUE value; + char unique_name[DB_MAX_IDENTIFIER_LENGTH + 1]; + unique_name[0] = '\0'; + + int type; + set_get_element (grants, GRANT_ENTRY_TYPE (grant_index), &value); + type = db_get_int (&value); set_get_element (grants, GRANT_ENTRY_CLASS (grant_index), &value); - fprintf (fp, msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_AUTHORIZATION, MSGCAT_AUTH_CLASS_NAME), - sm_get_ch_name (db_get_object (&value))); + + if (type == DB_OBJECT_CLASS) + { + fprintf (fp, msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_AUTHORIZATION, MSGCAT_AUTH_CLASS_NAME), + sm_get_ch_name (db_get_object (&value))); + } + else + { + if (jsp_get_unique_name (db_get_object (&value), unique_name, DB_MAX_IDENTIFIER_LENGTH) == NULL) + { + assert (er_errid () != NO_ERROR); + } + + fprintf (fp, msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_AUTHORIZATION, MSGCAT_AUTH_CLASS_NAME), unique_name); + } fprintf (fp, " "); set_get_element (grants, GRANT_ENTRY_SOURCE (grant_index), &value); @@ -831,8 +1306,8 @@ get_grants (MOP auth, DB_SET **grant_ptr, int filter) int error = NO_ERROR; DB_VALUE value; DB_SET *grants = NULL; - MOP grantor, gowner, class_; - int gsize, i, j, existing, cache; + MOP grantor, gowner, gtype, obj_; + int gsize, i, j, existing, cache, obj_type; bool need_pop_er_stack = false; assert (grant_ptr != NULL); @@ -857,14 +1332,14 @@ get_grants (MOP auth, DB_SET **grant_ptr, int filter) goto end; } + grants = db_get_set (&value); + gsize = set_size (grants); + if (!filter) { goto end; } - grants = db_get_set (&value); - gsize = set_size (grants); - /* there might be errors */ error = er_errid (); if (error != NO_ERROR) @@ -874,6 +1349,13 @@ get_grants (MOP auth, DB_SET **grant_ptr, int filter) for (i = 0; i < gsize; i += GRANT_ENTRY_LENGTH) { + error = set_get_element (grants, GRANT_ENTRY_TYPE (i), &value); + if (error != NO_ERROR) + { + goto end; + } + obj_type = db_get_int (&value); + error = set_get_element (grants, GRANT_ENTRY_SOURCE (i), &value); if (error != NO_ERROR) { @@ -892,7 +1374,7 @@ get_grants (MOP auth, DB_SET **grant_ptr, int filter) if (grantor == NULL) { - class_ = NULL; + obj_ = NULL; error = set_get_element (grants, GRANT_ENTRY_CLASS (i), &value); if (error != NO_ERROR) { @@ -901,14 +1383,14 @@ get_grants (MOP auth, DB_SET **grant_ptr, int filter) if (DB_VALUE_TYPE (&value) == DB_TYPE_OBJECT && !DB_IS_NULL (&value)) { - class_ = db_get_object (&value); - if (WS_IS_DELETED (class_)) + obj_ = db_get_object (&value); + if (WS_IS_DELETED (obj_)) { - class_ = NULL; + obj_ = NULL; } } - if (class_ == NULL) + if (obj_ == NULL) { /* class is bad too, remove this entry */ drop_grant_entry (grants, i); @@ -917,7 +1399,14 @@ get_grants (MOP auth, DB_SET **grant_ptr, int filter) else { /* this will at least be DBA */ - gowner = au_get_class_owner (class_); + if (obj_type == DB_OBJECT_CLASS) + { + gowner = au_get_class_owner (obj_); + } + else + { + gowner = jsp_get_owner (obj_); + } /* see if there's already an entry for this */ existing = -1; @@ -937,6 +1426,13 @@ get_grants (MOP auth, DB_SET **grant_ptr, int filter) if (existing == -1) { + db_make_int (&value, obj_type); + error = set_put_element (grants, GRANT_ENTRY_TYPE (i), &value); + if (error != NO_ERROR) + { + goto end; + } + /* * no previous entry for the owner, * use the current one @@ -1082,6 +1578,7 @@ collect_class_grants (MOP class_mop, DB_AUTH type, MOP revoked_auth, int revoked DB_QUERY_ERROR query_error; DB_VALUE user_val; const char *qp1 = "select [%s] from [%s];"; + int saved_opt_level; *return_grants = NULL; @@ -1094,7 +1591,14 @@ collect_class_grants (MOP class_mop, DB_AUTH type, MOP revoked_auth, int revoked } sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME); + + saved_opt_level = prm_get_integer_value (PRM_ID_OPTIMIZATION_LEVEL); + prm_set_integer_value (PRM_ID_OPTIMIZATION_LEVEL, 1); + error = db_compile_and_execute_local (query, &query_result, &query_error); + + prm_set_integer_value (PRM_ID_OPTIMIZATION_LEVEL, saved_opt_level); + if (error < 0) /* error is row count if not negative. */ { @@ -1218,16 +1722,16 @@ collect_class_grants (MOP class_mop, DB_AUTH type, MOP revoked_auth, int revoked return (error); } - /* * propagate_revoke - Propagates a revoke operation to all affected users. * return: error code + * obj_type(in): type of the database object * grant_list(in): list of grant nodes - * owner(in): owner of the class + * owner(in): owner of the database object * mask(in): authorization type mask */ static int -propagate_revoke (AU_GRANT *grant_list, MOP owner, DB_AUTH mask) +propagate_revoke (DB_OBJECT_TYPE obj_type, AU_GRANT *grant_list, MOP owner, DB_AUTH mask) { int error = NO_ERROR; DB_VALUE element; @@ -1242,7 +1746,7 @@ propagate_revoke (AU_GRANT *grant_list, MOP owner, DB_AUTH mask) if (catcls_Enable == true) #endif /* SA_MODE */ { - error = au_propagate_del_new_auth (grant_list, mask); + error = au_propagate_del_new_auth (obj_type, grant_list, mask); if (error != NO_ERROR) { return error; @@ -1336,11 +1840,11 @@ propagate_revoke (AU_GRANT *grant_list, MOP owner, DB_AUTH mask) * mask(in): */ static int -au_propagate_del_new_auth (AU_GRANT *glist, DB_AUTH mask) +au_propagate_del_new_auth (DB_OBJECT_TYPE obj_type, AU_GRANT *glist, DB_AUTH mask) { AU_GRANT *g; DB_SET *grants; - DB_VALUE class_, type; + DB_VALUE obj_, type; int error = NO_ERROR; au_auth_accessor accessor; @@ -1354,7 +1858,7 @@ au_propagate_del_new_auth (AU_GRANT *glist, DB_AUTH mask) break; } - error = set_get_element (grants, GRANT_ENTRY_CLASS (g->grant_index), &class_); + error = set_get_element (grants, GRANT_ENTRY_CLASS (g->grant_index), &obj_); if (error != NO_ERROR) { break; @@ -1366,8 +1870,10 @@ au_propagate_del_new_auth (AU_GRANT *glist, DB_AUTH mask) break; } + // NOTE: Only DB_OBJECT_CLASS error = - accessor.delete_auth (g->grantor, g->user, db_get_object (&class_), (DB_AUTH) (db_get_int (&type) & ~mask)); + accessor.delete_auth (obj_type, g->grantor, g->user, db_get_object (&obj_), + (DB_AUTH) (db_get_int (&type) & ~mask)); if (error != NO_ERROR) { break; @@ -1378,6 +1884,120 @@ au_propagate_del_new_auth (AU_GRANT *glist, DB_AUTH mask) return error; } +/* + * au_compare_grantor_and_return - + * return: error code + * grantor(out): return the class_owner or login_user + * obj_mop(in): mop of the object + * type(in) : authorization type + * login_user(in) : current login_user (Au_user) + * class_owner(in) : owner of the object + * drop_user(in) : used when executing the drop user statement + */ +static int +au_compare_grantor_and_return (MOP *grantor, MOP obj_mop, DB_AUTH type, MOP login_user, MOP class_owner, MOP drop_user) +{ + int error = NO_ERROR; + unsigned int cache, mask; + MOP auth; + DB_VALUE element; + DB_SET *grants; + int j, gsize; + + assert ((grantor != NULL && obj_mop != NULL && login_user != NULL && class_owner != NULL) || drop_user != NULL); + + *grantor = NULL; + + if (drop_user != NULL) + { + /* + * used when executing the drop user statement. + */ + *grantor = drop_user; + } + else if (au_is_dba_group_member (login_user) || au_is_user_group_member (class_owner, login_user)) + { + /* + * DBA, DBA Member, Owner, Owner Memeber + */ + *grantor = class_owner; + } + else + { + /* + * Check grantable user + */ + if (au_get_object (login_user, "authorization", &auth) != NO_ERROR) + { + error = ER_AU_ACCESS_ERROR; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 2, AU_USER_CLASS_NAME, "authorization"); + } + else if ((error = get_grants (auth, &grants, 1)) == NO_ERROR) + { + gsize = set_size (grants); + if (gsize) + { + for (j = 0; j < gsize && error == NO_ERROR; j += GRANT_ENTRY_LENGTH) + { + cache = AU_NO_AUTHORIZATION; + if (set_get_element (grants, GRANT_ENTRY_CLASS (j), &element)) + { + assert (er_errid () != NO_ERROR); + error = er_errid (); + break; + } + + if (db_get_object (&element) == obj_mop) + { + cache = AU_NO_AUTHORIZATION; + if (set_get_element (grants, GRANT_ENTRY_CACHE (j), &element)) + { + assert (er_errid () != NO_ERROR); + error = er_errid (); + break; + } + + cache = db_get_int (&element); + mask = (unsigned int) (type | (type << AU_GRANT_SHIFT)); + if ((cache & mask) != mask) + { + error = appropriate_error (cache, mask); + if (error) + { + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + break; + } + } + else + { + *grantor = login_user; + break; + } + } + } + } + set_free (grants); + + /* + * This error condition occurs in the following two cases, both of which are considered as lacking authorization: + * 1. gsize == 0: Indicates no prior authorization + * When the grants column in the db_authorization catalog is empty. + * 2. db_get_object(&element) != obj_mop: Indicates that permissions exist for other objects but not for the current one + * When the grants column in the db_authorization catalog contains permissions for other objects (such as classes or procedures), but lacks permissions for the obj_mop object. + */ + if (error == NO_ERROR && *grantor == NULL) + { + cache = 0; + mask = (unsigned int) type; + error = appropriate_error (cache, mask); + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + } + } + } + + return error; +} + /* * au_print_grants() - * return: none @@ -1439,8 +2059,9 @@ au_force_write_new_auth (void) MOP au_class, au_obj; DB_VALUE grants_val; DB_SET *grants; - DB_VALUE grantor_val, grantee_val, class_val, auth_val; - MOP grantor, grantee, class_; + DB_VALUE grantor_val, grantee_val, obj_val, auth_val, type_val; + MOP grantor, grantee, obj_; + DB_OBJECT_TYPE obj_type; DB_AUTH auth; int gindex, gsize; int save; @@ -1489,12 +2110,19 @@ au_force_write_new_auth (void) au_auth_accessor accessor; for (gindex = 0; gindex < gsize; gindex += GRANT_ENTRY_LENGTH) { - error = set_get_element (grants, GRANT_ENTRY_CLASS (gindex), &class_val); + error = set_get_element (grants, GRANT_ENTRY_TYPE (gindex), &type_val); if (error != NO_ERROR) { goto end; } - class_ = db_get_object (&class_val); + obj_type = (DB_OBJECT_TYPE) db_get_int (&type_val); + + error = set_get_element (grants, GRANT_ENTRY_CLASS (gindex), &obj_val); + if (error != NO_ERROR) + { + goto end; + } + obj_ = db_get_object (&obj_val); error = set_get_element (grants, GRANT_ENTRY_SOURCE (gindex), &grantor_val); if (error != NO_ERROR) @@ -1510,7 +2138,8 @@ au_force_write_new_auth (void) } auth = (DB_AUTH) db_get_int (&auth_val); - error = accessor.insert_auth (grantor, grantee, class_, (DB_AUTH) (auth & AU_TYPE_MASK), (auth & AU_GRANT_MASK)); + error = accessor.insert_auth (obj_type, grantor, grantee, obj_, (DB_AUTH) (auth & AU_TYPE_MASK), + (auth & AU_GRANT_MASK)); if (error != NO_ERROR) { goto end; @@ -1528,4 +2157,5 @@ au_force_write_new_auth (void) return error; } + #endif // SA_MODE diff --git a/src/object/authenticate_grant.hpp b/src/object/authenticate_grant.hpp index 1fe30fe7a1d..59e05e2ab7b 100644 --- a/src/object/authenticate_grant.hpp +++ b/src/object/authenticate_grant.hpp @@ -63,10 +63,12 @@ struct au_grant * */ -#define GRANT_ENTRY_LENGTH 3 -#define GRANT_ENTRY_CLASS(index) (index) -#define GRANT_ENTRY_SOURCE(index) ((index) + 1) -#define GRANT_ENTRY_CACHE(index) ((index) + 2) +#define GRANT_ENTRY_LENGTH 4 + +#define GRANT_ENTRY_TYPE(index) ((index)) +#define GRANT_ENTRY_CLASS(index) ((index) + 1) +#define GRANT_ENTRY_SOURCE(index) ((index) + 2) +#define GRANT_ENTRY_CACHE(index) ((index) + 3) extern int apply_grants (MOP auth, MOP class_mop, unsigned int *bits); extern int get_grants (MOP auth, DB_SET **grant_ptr, int filter); diff --git a/src/object/authenticate_migration.cpp b/src/object/authenticate_migration.cpp index ab5671aee58..15e4f400513 100644 --- a/src/object/authenticate_migration.cpp +++ b/src/object/authenticate_migration.cpp @@ -32,6 +32,7 @@ #include "schema_manager.h" /* sm_get_ch_name () */ #include "extract_schema.hpp" /* extract_context */ #include "printer.hpp" /* print_output */ +#include "jsp_cl.h" /* jsp_get_owner () */ /* * CLASS_GRANT @@ -86,8 +87,9 @@ static int add_class_grant (CLASS_AUTH *auth, MOP source, MOP user, int cache); static int build_class_grant_list (CLASS_AUTH *cl_auth, MOP class_mop); static void issue_grant_statement (extract_context &ctxt, print_output &output_ctx, CLASS_AUTH *auth, - CLASS_GRANT *grant, int authbits); -static int class_grant_loop (extract_context &ctxt, print_output &output_ctx, CLASS_AUTH *auth); + CLASS_GRANT *grant, int authbits, DB_OBJECT_TYPE obj_type); +static int class_grant_loop (extract_context &ctxt, print_output &output_ctx, CLASS_AUTH *auth, + DB_OBJECT_TYPE obj_type); /* * MIGRATION SUPPORT @@ -576,7 +578,7 @@ au_export_users (extract_context &ctxt, print_output &output_ctx) * quoted_id_flag(in): */ int -au_export_grants (extract_context &ctxt, print_output &output_ctx, MOP class_mop) +au_export_grants (extract_context &ctxt, print_output &output_ctx, MOP class_mop, DB_OBJECT_TYPE obj_type) { int error = NO_ERROR; CLASS_AUTH cl_auth; @@ -584,9 +586,23 @@ au_export_grants (extract_context &ctxt, print_output &output_ctx, MOP class_mop int statements, ecount; char *uname; - cl_auth.class_mop = class_mop; - cl_auth.owner = au_get_class_owner (class_mop); - cl_auth.users = NULL; + switch (obj_type) + { + case DB_OBJECT_CLASS: + cl_auth.class_mop = class_mop; + cl_auth.owner = au_get_class_owner (class_mop); + cl_auth.users = NULL; + break; + case DB_OBJECT_PROCEDURE: + cl_auth.class_mop = class_mop; + cl_auth.owner = jsp_get_owner (class_mop); + cl_auth.users = NULL; + break; + default: + assert (false); + error = ER_FAILED; + return (error); + } /* make an entry for the owner with complete authorization */ u = find_or_add_user (&cl_auth, cl_auth.owner); @@ -597,7 +613,7 @@ au_export_grants (extract_context &ctxt, print_output &output_ctx, MOP class_mop if (error == NO_ERROR) { /* loop through the grant list, issuing grant statements */ - while ((statements = class_grant_loop (ctxt, output_ctx, &cl_auth))) + while ((statements = class_grant_loop (ctxt, output_ctx, &cl_auth, obj_type))) ; for (u = cl_auth.users, ecount = 0; u != NULL; u = u->next) @@ -941,10 +957,11 @@ build_class_grant_list (CLASS_AUTH *cl_auth, MOP class_mop) */ static void issue_grant_statement (extract_context &ctxt, print_output &output_ctx, CLASS_AUTH *auth, CLASS_GRANT *grant, - int authbits) + int authbits, DB_OBJECT_TYPE obj_type) { const char *gtype; char owner_name[DB_MAX_IDENTIFIER_LENGTH] = { '\0' }; + char unique_name[DB_MAX_IDENTIFIER_LENGTH + 1]; char *class_name = NULL; char *username; int typebit; @@ -977,10 +994,29 @@ issue_grant_statement (extract_context &ctxt, print_output &output_ctx, CLASS_AU gtype = "???"; break; } - SPLIT_USER_SPECIFIED_NAME (sm_get_ch_name (auth->class_mop), owner_name, class_name); - username = au_get_user_name (grant->user->obj); - output_ctx ("GRANT %s ON ", gtype); + output_ctx ("\n"); + + switch (obj_type) + { + case DB_OBJECT_CLASS: + SPLIT_USER_SPECIFIED_NAME (sm_get_ch_name (auth->class_mop), owner_name, class_name); + username = au_get_user_name (grant->user->obj); + + output_ctx ("GRANT %s ON ", gtype); + break; + case DB_OBJECT_PROCEDURE: + unique_name[0] = '\0'; + jsp_get_unique_name (auth->class_mop, unique_name, DB_MAX_IDENTIFIER_LENGTH + 1); + SPLIT_USER_SPECIFIED_NAME (unique_name, owner_name, class_name); + username = au_get_user_name (grant->user->obj); + + output_ctx ("GRANT %s ON PROCEDURE ", gtype); + break; + default: + output_ctx ("GRANT %s ON ", gtype); + break; + } if (ctxt.is_dba_user || ctxt.is_dba_group_member) { @@ -1036,7 +1072,7 @@ issue_grant_statement (extract_context &ctxt, print_output &output_ctx, CLASS_AU * TODO : LP64 */ static int -class_grant_loop (extract_context &ctxt, print_output &output_ctx, CLASS_AUTH *auth) +class_grant_loop (extract_context &ctxt, print_output &output_ctx, CLASS_AUTH *auth, DB_OBJECT_TYPE obj_type) { #define AU_MIN_BIT 1 /* AU_SELECT */ #define AU_MAX_BIT 0x40 /* AU_EXECUTE */ @@ -1066,7 +1102,7 @@ class_grant_loop (extract_context &ctxt, print_output &output_ctx, CLASS_AUTH *a { if (!ws_is_same_object (auth->users->obj, grant->user->obj)) { - issue_grant_statement (ctxt, output_ctx, auth, grant, authbits); + issue_grant_statement (ctxt, output_ctx, auth, grant, authbits, obj_type); } /* turn on grant bits in the granted user */ diff --git a/src/object/authenticate_owner.cpp b/src/object/authenticate_owner.cpp index 46f97e0f14e..365720ee8f3 100644 --- a/src/object/authenticate_owner.cpp +++ b/src/object/authenticate_owner.cpp @@ -478,7 +478,16 @@ au_change_sp_owner (MOP sp, MOP owner) { int error = NO_ERROR; int save; - DB_VALUE value; + const char *name_str = NULL, *owner_str = NULL; + char new_name_str[DB_MAX_IDENTIFIER_LENGTH]; + new_name_str[0]= '\0'; + char downcase_owner_name[DB_MAX_USER_LENGTH]; + downcase_owner_name[0] = '\0'; + DB_VALUE value, name_value, owner_value; + + db_make_null (&value); + db_make_null (&name_value); + db_make_null (&owner_value); AU_DISABLE (save); if (!au_is_dba_group_member (Au_user)) @@ -488,6 +497,31 @@ au_change_sp_owner (MOP sp, MOP owner) } else { + error = obj_get (sp, "sp_name", &name_value); + if (error != NO_ERROR) + { + goto end; + } + error = obj_get (owner, "name", &owner_value); + if (error != NO_ERROR) + { + goto end; + } + + name_str = db_get_string (&name_value); + owner_str = db_get_string (&owner_value); + + sm_downcase_name (owner_str, downcase_owner_name, DB_MAX_USER_LENGTH); + sprintf (new_name_str, "%s.%s", downcase_owner_name, name_str); + + /* change the unique_name */ + db_make_string (&value, new_name_str); + error = obj_set (sp, SP_ATTR_UNIQUE_NAME, &value); + if (error < 0) + { + goto end; + } + db_make_object (&value, owner); error = obj_set (sp, SP_ATTR_OWNER, &value); if (error < 0) diff --git a/src/object/object_representation.c b/src/object/object_representation.c index be1723f63c5..56b90833500 100644 --- a/src/object/object_representation.c +++ b/src/object/object_representation.c @@ -37,7 +37,7 @@ #include "error_manager.h" #include "file_io.h" #include "log_lsa.hpp" -#include "method_def.hpp" + #include "object_primitive.h" #include "object_representation.h" #include "oid.h" @@ -78,8 +78,6 @@ int mvcc_header_size_lookup[8] = { }; static TP_DOMAIN *unpack_domain (OR_BUF * buf, int *is_null); -static char *or_pack_method_sig (char *ptr, void *method_sig_ptr); -static char *or_unpack_method_sig (char *ptr, void **method_sig_ptr, int n); #if defined(ENABLE_UNUSED_FUNCTION) static char *unpack_str_array (char *buffer, char ***string_array, int count); #endif @@ -5649,37 +5647,6 @@ or_listid_length (void *listid_ptr) return length; } -/* - * or_pack_method_sig - packs a METHOD_SIG descriptor. - * return: advanced buffer pointer - * ptr(out): starting pointer - * method_sig_ptr(in): opaque pointer to METHOD_SIG structure - */ -static char * -or_pack_method_sig (char *ptr, void *method_sig_ptr) -{ - METHOD_SIG *method_sig = (METHOD_SIG *) method_sig_ptr; - int n; - - if (method_sig == (METHOD_SIG *) 0) - { - return ptr; - } - - ptr = or_pack_method_sig (ptr, method_sig->next); - ptr = or_pack_string (ptr, method_sig->method_name); - ptr = or_pack_string (ptr, method_sig->class_name); - ptr = or_pack_int (ptr, method_sig->method_type); - ptr = or_pack_int (ptr, method_sig->num_method_args); - - for (n = 0; n < method_sig->num_method_args + 1; n++) - { - ptr = or_pack_int (ptr, method_sig->method_arg_pos[n]); - } - - return ptr; -} - /* * or_pack_key_val_range - packs a KEY VALUE RANGE. * return: advanced buffer pointer @@ -5730,153 +5697,6 @@ or_unpack_key_val_range (char *ptr, void *key_val_range_ptr) return ptr; } -/* - * or_unpack_method_sig - unpacks a METHOD_SIG descriptor from a buffer. - * return: advanced buffer pointer - * ptr(in): starting pointer - * method_sig_ptr(out): method_sig descriptor - * n(in): - */ -static char * -or_unpack_method_sig (char *ptr, void **method_sig_ptr, int n) -{ - METHOD_SIG *method_sig; - - if (n == 0) - { - *(METHOD_SIG **) method_sig_ptr = (METHOD_SIG *) 0; - return ptr; - } - method_sig = (METHOD_SIG *) db_private_alloc (NULL, sizeof (METHOD_SIG)); - - if (method_sig == (METHOD_SIG *) 0) - { - return NULL; - } - ptr = or_unpack_method_sig (ptr, (void **) &method_sig->next, n - 1); - ptr = or_unpack_string (ptr, &method_sig->method_name); - ptr = or_unpack_string (ptr, &method_sig->class_name); - ptr = or_unpack_int (ptr, (int *) &method_sig->method_type); - ptr = or_unpack_int (ptr, &method_sig->num_method_args); - - method_sig->method_arg_pos = (int *) db_private_alloc (NULL, sizeof (int) * (method_sig->num_method_args + 1)); - if (method_sig->method_arg_pos == (int *) 0) - { - db_private_free_and_init (NULL, method_sig); - return NULL; - } - - for (n = 0; n < method_sig->num_method_args + 1; n++) - { - ptr = or_unpack_int (ptr, &method_sig->method_arg_pos[n]); - } - - *(METHOD_SIG **) method_sig_ptr = method_sig; - - return ptr; -} - -/* - * or_pack_method_sig_list - write a method signature list - * return: advanced buffer pointer - * ptr(out): starting pointer - * method_sig_list_ptr(in): method_sig_list descriptor - * Note: - * This packs a METHOD_SIG_LIST descriptor. - */ -char * -or_pack_method_sig_list (char *ptr, void *method_sig_list_ptr) -{ - METHOD_SIG_LIST *method_sig_list = (METHOD_SIG_LIST *) method_sig_list_ptr; - - ptr = or_pack_int (ptr, method_sig_list->num_methods); - -#if !defined(NDEBUG) - { - int i = 0; - METHOD_SIG *sig; - - for (sig = method_sig_list->method_sig; sig; sig = sig->next) - { - i++; - } - assert (method_sig_list->num_methods == i); - } -#endif - - ptr = or_pack_method_sig (ptr, method_sig_list->method_sig); - return ptr; -} - -/* - * or_unpack_method_sig_list - read a method signature list - * return: advanced buffer pointer - * ptr(in): starting pointer - * method_sig_list_ptr(out): method_sig_list descriptor - * Note: - * This unpacks a METHOD_SIG_LIST descriptor from a buffer. - */ -char * -or_unpack_method_sig_list (char *ptr, void **method_sig_list_ptr) -{ - METHOD_SIG_LIST *method_sig_list; - - method_sig_list = (METHOD_SIG_LIST *) db_private_alloc (NULL, sizeof (METHOD_SIG_LIST)); - if (method_sig_list == (METHOD_SIG_LIST *) 0) - { - return NULL; - } - - ptr = or_unpack_int (ptr, &method_sig_list->num_methods); - ptr = or_unpack_method_sig (ptr, (void **) &method_sig_list->method_sig, method_sig_list->num_methods); - -#if !defined(NDEBUG) - { - int i = 0; - METHOD_SIG *sig; - - for (sig = method_sig_list->method_sig; sig; sig = sig->next) - { - i++; - } - assert (method_sig_list->num_methods == i); - } -#endif - - *(METHOD_SIG_LIST **) method_sig_list_ptr = method_sig_list; - - return ptr; -} - -/* - * or_method_sig_list_length - get the length of method signature list - * return: length of METHOD_SIG_LIST in bytes. - * method_sig_list_ptr(in): method_sig_list descriptor - * Note: - * Calculates the number of bytes required to store the disk/comm - * representation of a METHOD_SIG_LIST structure. - */ -int -or_method_sig_list_length (void *method_sig_list_ptr) -{ - METHOD_SIG_LIST *method_sig_list = (METHOD_SIG_LIST *) method_sig_list_ptr; - METHOD_SIG *method_sig; - int length = OR_INT_SIZE; /* num_methods */ - int n; - - for (n = 0, method_sig = method_sig_list->method_sig; n < method_sig_list->num_methods; - ++n, method_sig = method_sig->next) - { - length += or_packed_string_length (method_sig->method_name, NULL); - length += or_packed_string_length (method_sig->class_name, NULL); - length += OR_INT_SIZE * 2; /* method_type & num_method_args */ - /* + object ptr */ - length += OR_INT_SIZE * (method_sig->num_method_args + 1); - /* method_arg_pos */ - } - return length; -} - /* * GENERIC DB_VALUE PACKING */ diff --git a/src/object/schema_class_truncator.cpp b/src/object/schema_class_truncator.cpp index 46aa1533341..a1a977177f3 100644 --- a/src/object/schema_class_truncator.cpp +++ b/src/object/schema_class_truncator.cpp @@ -528,7 +528,7 @@ namespace cubschema STATEMENT_ID stmt_id; DB_VALUE value; char select_query[DB_MAX_IDENTIFIER_LENGTH + 256] = { 0 }; - constexpr int CNT_CATCLS_OBJECTS = 5; + constexpr int CNT_CATCLS_OBJECTS = 6; DB_BIGINT cnt_refers = CNT_CATCLS_OBJECTS + 1; int au_save; @@ -544,13 +544,13 @@ namespace cubschema * To do this, we use an walkaround in which we count the number of general object domains in existing system catalogs * and if the SELECT result is over this, we asuume that there are some general object domain in some user class. * - * The number is now 5 and hard-coded, so we MUST consider it when add or remove a general object domain in a system class. + * The number is now 6 and hard-coded, so we MUST consider it when add or remove a general object domain in a system class. * If it is changed, we MUST also change the value of CNT_CATCLS_OBJECTS. * - * We add a QA test case to confirm there are only 5 general object domains in system classes, which will help notice this constraint + * We add a QA test case to confirm there are only 6 general object domains in system classes, which will help notice this constraint * and this test case also has to be changed along if CNT_CATCLS_OBJECTS is changed. * - * See CBRD-23983 for the details. + * See CBRD-23983 and CBRD-25697 for the details. */ AU_DISABLE (au_save); diff --git a/src/object/schema_manager.c b/src/object/schema_manager.c index 42e1a8bcf81..50ae23eddd5 100644 --- a/src/object/schema_manager.c +++ b/src/object/schema_manager.c @@ -13568,6 +13568,7 @@ sm_delete_class_mop (MOP op, bool is_cascade_constraints) SM_CLASS_CONSTRAINT *pk; char *fk_name = NULL; const char *table_name; + MOP save_user, owner; if (op == NULL) { @@ -13826,8 +13827,30 @@ sm_delete_class_mop (MOP op, bool is_cascade_constraints) goto end; } + /* before deleting an object, all permissions are revoked. */ + owner = au_get_class_owner (op); + if (owner == NULL) + { + assert (er_errid () != NO_ERROR); + error = er_errid (); + goto end; + } + + save_user = Au_user; + if (AU_SET_USER (owner) == NO_ERROR) + { + error = au_object_revoke_all_privileges (DB_OBJECT_CLASS, owner, table_name); + if (error != NO_ERROR) + { + AU_SET_USER (save_user); + goto end; + } + } + + AU_SET_USER (save_user); + /* now delete _db_auth tuples refers to the table */ - error = au_delete_auth_of_dropping_table (table_name); + error = au_delete_auth_of_dropping_database_object (DB_OBJECT_CLASS, table_name); if (error != NO_ERROR) { goto end; diff --git a/src/object/schema_system_catalog.cpp b/src/object/schema_system_catalog.cpp index 1ae1e406745..4a560c8cbb9 100644 --- a/src/object/schema_system_catalog.cpp +++ b/src/object/schema_system_catalog.cpp @@ -72,6 +72,7 @@ namespace cubschema CT_PARTITION_NAME, // "_db_partition" CT_STORED_PROC_NAME, // "_db_stored_procedure" CT_STORED_PROC_ARGS_NAME, // "_db_stored_procedure_args" + CT_STORED_PROC_CODE_NAME, // "_db_stored_procedure_code" CT_SERIAL_NAME, // "db_serial" CT_HA_APPLY_INFO_NAME, // "db_ha_apply_info" CT_COLLATION_NAME, // "_db_collation" diff --git a/src/object/schema_system_catalog_builder.cpp b/src/object/schema_system_catalog_builder.cpp index 3062006e35a..bd60631ed17 100644 --- a/src/object/schema_system_catalog_builder.cpp +++ b/src/object/schema_system_catalog_builder.cpp @@ -179,7 +179,7 @@ namespace cubschema for (const grant &g : auth.grants) { - error_code = au_grant (g.target_user, class_mop, g.auth, g.with_grant_option); + error_code = au_grant (DB_OBJECT_CLASS, g.target_user, class_mop, g.auth, g.with_grant_option); if (error_code != NO_ERROR) { assert (false); @@ -253,7 +253,7 @@ namespace cubschema for (const grant &g : auth.grants) { assert (g.target_user != nullptr); - error_code = au_grant (g.target_user, class_mop, g.auth, g.with_grant_option); + error_code = au_grant (DB_OBJECT_CLASS, g.target_user, class_mop, g.auth, g.with_grant_option); if (error_code != NO_ERROR) { return error_code; diff --git a/src/object/schema_system_catalog_constants.h b/src/object/schema_system_catalog_constants.h index 8838ac4ab79..909dcb98dbe 100644 --- a/src/object/schema_system_catalog_constants.h +++ b/src/object/schema_system_catalog_constants.h @@ -40,6 +40,7 @@ #define CT_DATATYPE_NAME "_db_data_type" #define CT_STORED_PROC_NAME "_db_stored_procedure" #define CT_STORED_PROC_ARGS_NAME "_db_stored_procedure_args" +#define CT_STORED_PROC_CODE_NAME "_db_stored_procedure_code" #define CT_PARTITION_NAME "_db_partition" #define CT_SERIAL_NAME "db_serial" #define CT_HA_APPLY_INFO_NAME "db_ha_apply_info" diff --git a/src/object/schema_system_catalog_definition.hpp b/src/object/schema_system_catalog_definition.hpp index d5b3bc850f7..ed8d583363f 100644 --- a/src/object/schema_system_catalog_definition.hpp +++ b/src/object/schema_system_catalog_definition.hpp @@ -33,7 +33,6 @@ namespace cubschema { - enum class attribute_kind { COLUMN, diff --git a/src/object/schema_system_catalog_install.cpp b/src/object/schema_system_catalog_install.cpp index 6a073daaf24..8f4220b2a52 100644 --- a/src/object/schema_system_catalog_install.cpp +++ b/src/object/schema_system_catalog_install.cpp @@ -224,6 +224,7 @@ catcls_init (void) ADD_TABLE_DEFINITION (CT_DATATYPE_NAME, system_catalog_initializer::get_data_type()); ADD_TABLE_DEFINITION (CT_STORED_PROC_NAME, system_catalog_initializer::get_stored_procedure()); ADD_TABLE_DEFINITION (CT_STORED_PROC_ARGS_NAME, system_catalog_initializer::get_stored_procedure_arguments()); + ADD_TABLE_DEFINITION (CT_STORED_PROC_CODE_NAME, system_catalog_initializer::get_stored_procedure_code()); ADD_TABLE_DEFINITION (CT_SERIAL_NAME, system_catalog_initializer::get_serial()); ADD_TABLE_DEFINITION (CT_HA_APPLY_INFO_NAME, system_catalog_initializer::get_ha_apply_info()); ADD_TABLE_DEFINITION (CT_COLLATION_NAME, system_catalog_initializer::get_collations()); @@ -743,7 +744,8 @@ namespace cubschema { {"grantor", AU_USER_CLASS_NAME}, {"grantee", AU_USER_CLASS_NAME}, - {"class_of", CT_CLASS_NAME}, + {"object_type", "integer"}, + {"object_of", "object"}, {"auth_type", format_varchar (7)}, {"is_grantable", "integer"} }, @@ -756,7 +758,7 @@ namespace cubschema // owner, grants Au_dba_user, {} }, -// initializer +// initializers nullptr ); @@ -831,19 +833,24 @@ namespace cubschema CT_STORED_PROC_NAME, // columns { + {"unique_name", format_varchar (255)}, {"sp_name", format_varchar (255)}, {"sp_type", "integer"}, {"return_type", "integer"}, {"arg_count", "integer"}, {"args", format_sequence (CT_STORED_PROC_ARGS_NAME)}, {"lang", "integer"}, - {"target", format_varchar (4096)}, + {"pkg_name", format_varchar (255)}, + {"is_system_generated", "integer"}, + {"directive", "integer"}, + {"target_class", format_varchar (1024)}, + {"target_method", format_varchar (1024)}, {"owner", AU_USER_CLASS_NAME}, {"comment", format_varchar (1024)} }, // constraints { - {DB_CONSTRAINT_UNIQUE, "", {"sp_name", nullptr}, false}, + {DB_CONSTRAINT_PRIMARY_KEY, "pk_db_stored_procedure_unique_name", {"unique_name", nullptr}, false} }, // authorization { @@ -853,8 +860,6 @@ namespace cubschema // initializer nullptr ); - - } system_catalog_definition @@ -866,16 +871,20 @@ namespace cubschema CT_STORED_PROC_ARGS_NAME, // columns { - {"sp_name", format_varchar (255)}, + {"sp_of", CT_STORED_PROC_NAME}, + {"pkg_name", format_varchar (255)}, {"index_of", "integer"}, + {"is_system_generated", "integer"}, {"arg_name", format_varchar (255)}, {"data_type", "integer"}, {"mode", "integer"}, + {"default_value", format_varchar (255)}, // TODO: CBRD-25261 + {"is_optional", "integer"}, // default_value is used only when is_optional is 1 {"comment", format_varchar (1024)}, }, // constraints { - {DB_CONSTRAINT_INDEX, "", {"sp_name", nullptr}, false}, + {DB_CONSTRAINT_INDEX, "", {"sp_of", nullptr}, false}, }, // authorization { @@ -885,8 +894,40 @@ namespace cubschema // initializer nullptr ); + } + system_catalog_definition + system_catalog_initializer::get_stored_procedure_code () + { + + return system_catalog_definition ( + // name + CT_STORED_PROC_CODE_NAME, + // columns + { + {"name", format_varchar (1024)}, // same with [_db_stored_procedure].[target_class] + {"created_time", format_varchar (16)}, + {"owner", AU_USER_CLASS_NAME}, + {"is_static", "integer"}, + {"is_system_generated", "integer"}, + {"stype", "integer"}, + {"scode", format_varchar (1073741823)}, + {"otype", "integer"}, + {"ocode", format_varchar (1073741823)} + }, +// constraints + { + {DB_CONSTRAINT_PRIMARY_KEY, "", {"name", nullptr}, false} + }, +// authorization + { + // owner, grants + Au_dba_user, {} + }, +// initializer + nullptr + ); } system_catalog_definition @@ -1658,7 +1699,8 @@ namespace cubschema { {"grantor_name", "varchar(255)"}, {"grantee_name", "varchar(255)"}, - {"class_name", "varchar(255)"}, + {"object_type", "varchar(16)"}, + {"object_name", "varchar(255)"}, {"owner_name", "varchar(255)"}, {"auth_type", "varchar(7)"}, {"is_grantable", "varchar(3)"}, @@ -1767,12 +1809,15 @@ namespace cubschema // columns { {"sp_name", "varchar(255)"}, + {"pkg_name", "varchar (255)"}, {"sp_type", "varchar(16)"}, {"return_type", "varchar(16)"}, {"arg_count", "integer"}, {"lang", "varchar(16)"}, + {"authid", "varchar(16)"}, {"target", "varchar(4096)"}, {"owner", "varchar(256)"}, + {"code", format_varchar (1073741823)}, {"comment", "varchar(1024)"}, // query specs {attribute_kind::QUERY_SPEC, sm_define_view_stored_procedure_spec ()} @@ -1804,6 +1849,8 @@ namespace cubschema // columns { {"sp_name", "varchar(255)"}, + {"owner_name", "varchar(255)"}, + {"pkg_name", "varchar (255)"}, {"index_of", "integer"}, {"arg_name", "varchar(255)"}, {"data_type", "varchar(16)"}, diff --git a/src/object/schema_system_catalog_install.hpp b/src/object/schema_system_catalog_install.hpp index 7dd89dc710a..98133d956e9 100644 --- a/src/object/schema_system_catalog_install.hpp +++ b/src/object/schema_system_catalog_install.hpp @@ -47,6 +47,7 @@ namespace cubschema static system_catalog_definition get_partition (); static system_catalog_definition get_data_type (); static system_catalog_definition get_stored_procedure (); + static system_catalog_definition get_stored_procedure_code (); static system_catalog_definition get_stored_procedure_arguments (); static system_catalog_definition get_serial (); diff --git a/src/object/schema_system_catalog_install_query_spec.cpp b/src/object/schema_system_catalog_install_query_spec.cpp index 1f67e84d48a..42b7aa3a292 100644 --- a/src/object/schema_system_catalog_install_query_spec.cpp +++ b/src/object/schema_system_catalog_install_query_spec.cpp @@ -68,7 +68,7 @@ sm_define_view_class_spec (void) "SELECT " "[c].[class_name] AS [class_name], " "CAST ([c].[owner].[name] AS VARCHAR(255)) AS [owner_name], " /* string -> varchar(255) */ - "CASE [c].[class_type] WHEN 0 THEN 'CLASS' WHEN 1 THEN 'VCLASS' ELSE 'UNKNOW' END AS [class_type], " + "CASE [c].[class_type] WHEN 0 THEN 'CLASS' WHEN 1 THEN 'VCLASS' ELSE 'UNKNOWN' END AS [class_type], " "CASE WHEN MOD ([c].[is_system_class], 2) = 1 THEN 'YES' ELSE 'NO' END AS [is_system_class], " "CASE [c].[tde_algorithm] WHEN 0 THEN 'NONE' WHEN 1 THEN 'AES' WHEN 2 THEN 'ARIA' END AS [tde_algorithm], " "CASE " @@ -105,9 +105,9 @@ sm_define_view_class_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[c]} SUBSETEQ (" + "OR {[c].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -170,9 +170,9 @@ sm_define_view_super_class_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[c]} SUBSETEQ (" + "OR {[c].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -236,9 +236,9 @@ sm_define_view_vclass_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[q].[class_of]} SUBSETEQ (" + "OR {[q].[class_of].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -334,9 +334,9 @@ sm_define_view_attribute_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[c]} SUBSETEQ (" + "OR {[c].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -418,9 +418,9 @@ sm_define_view_attribute_set_domain_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[c]} SUBSETEQ (" + "OR {[c].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -492,9 +492,9 @@ sm_define_view_method_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[m].[class_of]} SUBSETEQ (" + "OR {[m].[class_of].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -573,9 +573,9 @@ sm_define_view_method_argument_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[s].[meth_of].[class_of]} SUBSETEQ (" + "OR {[s].[meth_of].[class_of].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -656,9 +656,9 @@ sm_define_view_method_argument_set_domain_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[s].[meth_of].[class_of]} SUBSETEQ (" + "OR {[s].[meth_of].[class_of].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -723,9 +723,9 @@ sm_define_view_method_file_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[f].[class_of]} SUBSETEQ (" + "OR {[f].[class_of].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -837,9 +837,9 @@ sm_define_view_index_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[i].[class_of]} SUBSETEQ (" + "OR {[i].[class_of].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -914,9 +914,9 @@ sm_define_view_index_key_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[k].[index_of].[class_of]} SUBSETEQ (" + "OR {[k].[index_of].[class_of].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -946,21 +946,25 @@ sm_define_view_index_key_spec (void) const char * sm_define_view_authorization_spec (void) { - static char stmt [2048]; + static char stmt [4096]; // *INDENT-OFF* sprintf (stmt, "SELECT " "CAST ([a].[grantor].[name] AS VARCHAR(255)) AS [grantor_name], " /* string -> varchar(255) */ "CAST ([a].[grantee].[name] AS VARCHAR(255)) AS [grantee_name], " /* string -> varchar(255) */ - "[a].[class_of].[class_name] AS [class_name], " - "CAST ([a].[class_of].[owner].[name] AS VARCHAR(255)) AS [owner_name], " /* string -> varchar(255) */ + "CASE [c].[class_type] WHEN 0 THEN 'CLASS' WHEN 1 THEN 'VCLASS' ELSE 'UNKNOWN' END AS [object_type], " + "[c].[class_name] AS [object_name], " + "CAST ([c].[owner].[name] AS VARCHAR(255)) AS [owner_name], " /* string -> varchar(255) */ "[a].[auth_type] AS [auth_type], " "CASE [a].[is_grantable] WHEN 0 THEN 'NO' ELSE 'YES' END AS [is_grantable] " "FROM " - /* CT_CLASSAUTH_NAME */ - "[%s] AS [a] " + /* CT_CLASSAUTH_NAME, CT_CLASS_NAME */ + "[%s] AS [a], [%s] AS [c] " "WHERE " + "[a].[object_of] = [c].[class_of] " + "AND [a].[object_type] = 0 " + "AND ( " "{'DBA'} SUBSETEQ (" "SELECT " "SET {CURRENT_USER} + COALESCE (SUM (SET {[t].[g].[name]}), SET {}) " @@ -970,7 +974,7 @@ sm_define_view_authorization_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[a].[class_of].[owner].[name]} SUBSETEQ (" + "OR {[c].[owner].[name]} SUBSETEQ (" "SELECT " "SET {CURRENT_USER} + COALESCE (SUM (SET {[t].[g].[name]}), SET {}) " "FROM " @@ -979,9 +983,9 @@ sm_define_view_authorization_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[a].[class_of]} SUBSETEQ (" + "OR {[c].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -996,12 +1000,73 @@ sm_define_view_authorization_spec (void) "[u].[name] = CURRENT_USER" ") " "AND [au].[auth_type] = 'SELECT'" - ")", + ") ) " + "UNION ALL " + "SELECT " + "CAST ([a].[grantor].[name] AS VARCHAR(255)) AS [grantor_name], " /* string -> varchar(255) */ + "CAST ([a].[grantee].[name] AS VARCHAR(255)) AS [grantee_name], " /* string -> varchar(255) */ + "CASE [s].[sp_type] WHEN 1 THEN 'PROCEDURE' ELSE 'FUNCTION' END AS [object_type], " + "[s].[sp_name] AS [object_name], " + "CAST ([s].[owner].[name] AS VARCHAR(255)) AS [owner_name], " + "[a].[auth_type] AS [auth_type], " + "CASE [a].[is_grantable] WHEN 0 THEN 'NO' ELSE 'YES' END AS [is_grantable] " + "FROM " + /* CT_CLASSAUTH_NAME, CT_STORED_PROC_NAME */ + "[%s] AS [a], [%s] AS [s] " + "WHERE " + "[a].[object_of] = [s] " + "AND [a].[object_type] = 5 " + "AND ( " + "{'DBA'} SUBSETEQ (" + "SELECT " + "SET {CURRENT_USER} + COALESCE (SUM (SET {[t].[g].[name]}), SET {}) " + "FROM " + /* AU_USER_CLASS_NAME */ + "[%s] AS [u], TABLE ([u].[groups]) AS [t] ([g]) " + "WHERE " + "[u].[name] = CURRENT_USER" + ") " + "OR {[s].[owner].[name]} SUBSETEQ (" + "SELECT " + "SET {CURRENT_USER} + COALESCE (SUM (SET {[t].[g].[name]}), SET {}) " + "FROM " + /* AU_USER_CLASS_NAME */ + "[%s] AS [u], TABLE ([u].[groups]) AS [t] ([g]) " + "WHERE " + "[u].[name] = CURRENT_USER" + ") " + "OR {[s]} SUBSETEQ (" + "SELECT " + "SUM (SET {[au].[object_of]}) " + "FROM " + /* CT_CLASSAUTH_NAME */ + "[%s] AS [au] " + "WHERE " + "{[au].[grantee].[name]} SUBSETEQ (" + "SELECT " + "SET {CURRENT_USER} + COALESCE (SUM (SET {[t].[g].[name]}), SET {}) " + "FROM " + /* AU_USER_CLASS_NAME */ + "[%s] AS [u], TABLE ([u].[groups]) AS [t] ([g]) " + "WHERE " + "[u].[name] = CURRENT_USER" + ") " + "AND [au].[auth_type] = 'EXECUTE'" + ") ) ", CT_CLASSAUTH_NAME, + CT_CLASS_NAME, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME, CT_CLASSAUTH_NAME, - AU_USER_CLASS_NAME); + AU_USER_CLASS_NAME, + + CT_CLASSAUTH_NAME, + CT_STORED_PROC_NAME, + AU_USER_CLASS_NAME, + AU_USER_CLASS_NAME, + CT_CLASSAUTH_NAME, + AU_USER_CLASS_NAME + ); // *INDENT-ON* return stmt; @@ -1048,9 +1113,9 @@ sm_define_view_trigger_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[c]} SUBSETEQ (" /* Why [c] and not [t].[target_class]? */ + "OR {[c].[class_of]} SUBSETEQ (" /* Why [c] and not [t].[target_class]? */ "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -1122,9 +1187,9 @@ sm_define_view_partition_spec (void) "WHERE " "[u].[name] = CURRENT_USER" ") " - "OR {[p].[class_of]} SUBSETEQ (" + "OR {[p].[class_of].[class_of]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " @@ -1162,6 +1227,7 @@ sm_define_view_stored_procedure_spec (void) sprintf (stmt, "SELECT " "[sp].[sp_name] AS [sp_name], " + "[sp].[pkg_name] AS [pkg_name], " "CASE [sp].[sp_type] WHEN 1 THEN 'PROCEDURE' ELSE 'FUNCTION' END AS [sp_type], " "CASE [sp].[return_type] " "WHEN 0 THEN 'void' " @@ -1170,15 +1236,22 @@ sm_define_view_stored_procedure_spec (void) "ELSE (SELECT [t].[type_name] FROM [%s] AS [t] WHERE [sp].[return_type] = [t].[type_id]) " "END AS [return_type], " "[sp].[arg_count] AS [arg_count], " - "CASE [sp].[lang] WHEN 1 THEN 'JAVA' ELSE '' END AS [lang], " - "[sp].[target] AS [target], " + "CASE [sp].[lang] WHEN 0 THEN 'PLCSQL' WHEN 1 THEN 'JAVA' ELSE 'UNKNOWN' END AS [lang], " + "CASE [sp].[directive] & 1 WHEN 0 THEN 'DEFINER' ELSE 'CURRENT_USER' END AS [authid], " + "CONCAT ([sp].[target_class], '.', [sp].[target_method]) AS [target], " "CAST ([sp].[owner].[name] AS VARCHAR(255)) AS [owner], " /* string -> varchar(255) */ + "[sp_code].[scode] AS [code], " "[sp].[comment] AS [comment] " "FROM " /* CT_STORED_PROC_NAME */ - "[%s] AS [sp]", + "[%s] AS [sp] " + /* CT_STORED_PROC_CODE_NAME */ + "LEFT OUTER JOIN [%s] AS [sp_code] ON [sp].[target_class] = [sp_code].[name] " + "WHERE " + "[sp].[is_system_generated] = 0", CT_DATATYPE_NAME, - CT_STORED_PROC_NAME); + CT_STORED_PROC_NAME, + CT_STORED_PROC_CODE_NAME); // *INDENT-ON* return stmt; @@ -1192,7 +1265,9 @@ sm_define_view_stored_procedure_arguments_spec (void) // *INDENT-OFF* sprintf (stmt, "SELECT " - "[sp].[sp_name] AS [sp_name], " + "[sp].[sp_of].[sp_name] AS [sp_name], " + "CAST ([sp].[sp_of].[owner].[name] AS VARCHAR(255)) AS [sp_owner_name], " /* string -> varchar(255) */ + "[sp].[pkg_name] AS [pkg_name], " "[sp].[index_of] AS [index_of], " "[sp].[arg_name] AS [arg_name], " "CASE [sp].[data_type] " @@ -1205,8 +1280,9 @@ sm_define_view_stored_procedure_arguments_spec (void) "FROM " /* CT_STORED_PROC_ARGS_NAME */ "[%s] AS [sp] " + "WHERE [sp].[is_system_generated] = 0 " "ORDER BY " /* Is it possible to remove ORDER BY? */ - "[sp].[sp_name], " + "[sp].[sp_of].[sp_name], " "[sp].[index_of]", CT_DATATYPE_NAME, CT_STORED_PROC_ARGS_NAME); @@ -1368,7 +1444,7 @@ sm_define_view_db_server_spec (void) ") " "OR {[ds]} SUBSETEQ (" "SELECT " - "SUM (SET {[au].[class_of]}) " + "SUM (SET {[au].[object_of]}) " "FROM " /* CT_CLASSAUTH_NAME */ "[%s] AS [au] " diff --git a/src/object/trigger_manager.c b/src/object/trigger_manager.c index e4b76016d64..2bd5460431c 100644 --- a/src/object/trigger_manager.c +++ b/src/object/trigger_manager.c @@ -5099,7 +5099,7 @@ execute_activity (TR_TRIGGER * trigger, DB_TRIGGER_TIME tr_time, DB_OBJECT * cur { if (AU_SET_USER (save_user)) { - /* what can this mean ? */ + // what can this mean ? rstatus = TR_RETURN_ERROR; } } diff --git a/src/optimizer/query_graph.c b/src/optimizer/query_graph.c index c4ef557878c..dd6583c74c4 100644 --- a/src/optimizer/query_graph.c +++ b/src/optimizer/query_graph.c @@ -3749,13 +3749,6 @@ pt_is_pseudo_const (PT_NODE * expr) */ return true; - case PT_METHOD_CALL: - /* - * Even if there are columns(PT_NAME) in the parameter of the Java Stored Procedure(METHOD_CALL), - * it can be guaranteed to be evaluated by the time it is referenced. - */ - return true; - case PT_DOT_: /* * It would be nice if we could use expressions that are @@ -4034,6 +4027,21 @@ pt_is_pseudo_const (PT_NODE * expr) return false; } + case PT_METHOD_CALL: + PT_NODE * p; + /* + * Even if there are columns(PT_NAME) in the parameter of the Java Stored Procedure(METHOD_CALL), + * it can be guaranteed to be evaluated by the time it is referenced. + */ + for (p = expr->info.method_call.arg_list; p; p = p->next) + { + if (!pt_is_pseudo_const (p)) + { + return false; + } + } + return true; + case PT_FUNCTION: { /* diff --git a/src/parser/csql_grammar.y b/src/parser/csql_grammar.y index b7522b7c32e..d60cd82076b 100644 --- a/src/parser/csql_grammar.y +++ b/src/parser/csql_grammar.y @@ -166,7 +166,7 @@ static void pt_fill_conn_info_container(PARSER_CONTEXT *parser, int buffer_pos, #include "memory_alloc.h" #include "db_elo.h" #include "storage_common.h" -#include "jsp_cl.h" +#include "sp_constants.hpp" #include "db_function.hpp" #if defined (SUPPRESS_STRLEN_WARNING) @@ -490,7 +490,8 @@ char *g_query_string; int g_query_string_len; int g_original_buffer_len; -static char *g_plcsql_text; +static int pt_set_plcsql_body_impl(PT_NODE* node, PT_NODE* body, int start, int spec_start, int spec_end, int end); +static int g_plcsql_text_pos; /* * The behavior of location propagation when a rule is matched must @@ -554,7 +555,6 @@ static char *g_plcsql_text; %} -%initial-action {yybuffer_pos = 0;} %locations %glr-parser %define parse.error verbose @@ -661,6 +661,7 @@ static char *g_plcsql_text; %type opt_access_modifier %type deduplicate_key_mod_level %type opt_index_with_clause_no_online +%type opt_authid /*}}}*/ /* define rule type (node) */ @@ -710,6 +711,9 @@ static char *g_plcsql_text; %type serial_name %type synonym_name_without_dot %type synonym_name +%type procedure_or_function_name_without_dot +%type procedure_or_function_name +%type procedure_or_function_name_list %type opt_alter_synonym %type opt_identifier %type normal_or_class_attr_list_with_commas @@ -750,6 +754,7 @@ static char *g_plcsql_text; %type delete_stmt %type author_cmd_list %type authorized_cmd +%type authorized_execute_procedure_cmd %type opt_password %type opt_groups %type opt_members @@ -953,6 +958,8 @@ static char *g_plcsql_text; %type grant_head %type grant_cmd %type revoke_cmd +%type grant_proc_cmd +%type revoke_proc_cmd %type opt_from_table_spec_list %type method_file_list %type incr_arg_name_list__inc @@ -1031,6 +1038,7 @@ static char *g_plcsql_text; %type dblink_column_definition %type pl_language_spec +%type opt_sp_default_value %type table_column /*}}}*/ @@ -1348,7 +1356,6 @@ static char *g_plcsql_text; %token PROMOTE %token QUERY %token READ -%token REBUILD %token RECURSIVE %token REF %token REFERENCES @@ -1516,12 +1523,14 @@ static char *g_plcsql_text; %token ANALYZE %token ARCHIVE %token ARIA +%token AUTHID %token AUTO_INCREMENT %token BENCHMARK %token BIT_AND %token BIT_OR %token BIT_XOR %token BUFFER +%token CALLER %token CACHE %token CAPACITY %token CHARACTER_SET_ @@ -1533,6 +1542,7 @@ static char *g_plcsql_text; %token COLUMNS %token COMMENT %token COMMITTED +%token COMPILE %token COST %token CRITICAL %token CUME_DIST @@ -1541,6 +1551,7 @@ static char *g_plcsql_text; %token DBLINK %token DBNAME %token DECREMENT +%token DEFINER %token DENSE_RANK %token DONT_REUSE_OID %token ELT @@ -1653,6 +1664,7 @@ static char *g_plcsql_text; %token QUEUES %token RANGE_ %token RANK +%token REBUILD %token REGEXP_COUNT %token REGEXP_INSTR %token REGEXP_LIKE @@ -1669,6 +1681,7 @@ static char *g_plcsql_text; %token DISK_SIZE %token ROW_NUMBER %token SECTIONS +%token SEMICOLON %token SEPARATOR %token SERIAL %token SERVER @@ -1739,9 +1752,9 @@ stmt_done ; stmt_list - : stmt_list ';' %dprec 1 + : stmt_list SEMICOLON %dprec 1 {{ /* empty line*/ }} - | stmt_list ';' stmt %dprec 2 + | stmt_list SEMICOLON stmt %dprec 2 {{ if ($3 != NULL) @@ -1785,7 +1798,7 @@ stmt_list } DBG_PRINT}} - | ';' + | SEMICOLON {{ /* empty line*/ }} ; @@ -1863,7 +1876,7 @@ stmt allow_attribute_ordering = false; parser_hidden_incr_list = NULL; - g_plcsql_text = NULL; + g_plcsql_text_pos = -1; is_in_sp_func_type = false; assert(expecting_pl_lang_spec == 0); // initialized in parser_main() or parse_one_statement() DBG_PRINT}} @@ -3058,22 +3071,45 @@ create_stmt push_msg(MSGCAT_SYNTAX_INVALID_CREATE_PROCEDURE); expecting_pl_lang_spec = 1; } - identifier opt_sp_param_list /* 5, 6 */ - is_or_as pl_language_spec /* 7, 8 */ - opt_comment_spec /* 9 */ + procedure_or_function_name_without_dot /* 5 */ + opt_sp_param_list /* 6 */ + opt_authid /* 7 */ + is_or_as pl_language_spec /* 8, 9 */ + opt_comment_spec /* 10 */ { pop_msg(); } {{ DBG_TRACE_GRAMMAR(create_stmt, | CREATE opt_or_replace PROCEDURE~); PT_NODE *node = parser_pop_hint_node (); if (node) { + PT_NODE* body = $9; + if (body->info.sp_body.lang == SP_LANG_PLCSQL && body->info.sp_body.impl == NULL) + { + // In particular, this happens for two cases: + // . cubrid loaddb -s ... (loading a schema file with loaddb utility) + // . csql -i --no-single-line ... (running csql with -i and --no-single-line) + // in which case parser->original_buffer is NULL. + // Without the original buffer, We need to get the SQL user text from the file. + assert(this_parser->original_buffer == NULL); + assert(this_parser->file); + + int start = @1.buffer_pos - 6; // 6 : length of "create" + int spec_start = @8.buffer_pos; // right after is_or_as + int spec_end = @9.buffer_pos; + int end = @$.buffer_pos; + if (pt_set_plcsql_body_impl(node, body, start, spec_start, spec_end, end) < 0) { + PT_ERROR (this_parser, node, "failed to get the user SQL from the input file"); + } + } + node->info.sp.or_replace = $2; node->info.sp.name = $5; node->info.sp.type = PT_SP_PROCEDURE; + node->info.sp.auth_id = $7; node->info.sp.param_list = $6; node->info.sp.ret_type = PT_TYPE_NONE; node->info.sp.ret_data_type = NULL; - node->info.sp.body = $8; - node->info.sp.comment = $9; + node->info.sp.body = $9; + node->info.sp.comment = $10; } $$ = node; @@ -3089,23 +3125,46 @@ create_stmt push_msg(MSGCAT_SYNTAX_INVALID_CREATE_FUNCTION); expecting_pl_lang_spec = 1; } - identifier opt_sp_param_list /* 5, 6 */ + procedure_or_function_name_without_dot /* 5 */ + opt_sp_param_list /* 6 */ RETURN sp_return_type /* 7, 8 */ - is_or_as pl_language_spec /* 9, 10 */ - opt_comment_spec /* 11 */ + opt_authid /* 9 */ + is_or_as pl_language_spec /* 10, 11 */ + opt_comment_spec /* 12 */ { pop_msg(); } {{ DBG_TRACE_GRAMMAR(create_stmt, | CREATE opt_or_replace FUNCTION~); PT_NODE *node = parser_pop_hint_node (); if (node) { + PT_NODE* body = $11; + if (body->info.sp_body.lang == SP_LANG_PLCSQL && body->info.sp_body.impl == NULL) + { + // In particular, this happens for two cases: + // . cubrid loaddb -s ... (loading a schema file with loaddb utility) + // . csql -i --no-single-line ... (running csql with -i and --no-single-line) + // in which case parser->original_buffer is NULL. + // Without the original buffer, We need to get the SQL user text from the file. + assert(this_parser->original_buffer == NULL); + assert(this_parser->file); + + int start = @1.buffer_pos - 6; // 6 : length of "create" + int spec_start = @10.buffer_pos; // right after is_or_as + int spec_end = @11.buffer_pos; + int end = @$.buffer_pos; + if (pt_set_plcsql_body_impl(node, body, start, spec_start, spec_end, end) < 0) { + PT_ERROR (this_parser, node, "failed to get the user SQL from the input file"); + } + } + node->info.sp.or_replace = $2; node->info.sp.name = $5; node->info.sp.type = PT_SP_FUNCTION; + node->info.sp.auth_id = $9; node->info.sp.param_list = $6; node->info.sp.ret_type = (int) TO_NUMBER(CONTAINER_AT_0($8)); node->info.sp.ret_data_type = CONTAINER_AT_1($8); - node->info.sp.body = $10; - node->info.sp.comment = $11; + node->info.sp.body = $11; + node->info.sp.comment = $12; } $$ = node; @@ -4083,10 +4142,10 @@ alter_stmt DBG_PRINT}} | ALTER /* 1 */ procedure_or_function /* 2 */ - identifier /* 3 */ - opt_owner_clause /* 4 */ - opt_comment_spec /* 5 */ - {{ DBG_TRACE_GRAMMAR(alter_stmt, | ALTER procedure_or_function identifier opt_owner_clause opt_comment_spec); + procedure_or_function_name /* 3 */ + opt_owner_clause /* 4 */ + opt_comment_spec /* 5 */ + {{ DBG_TRACE_GRAMMAR(alter_stmt, | ALTER procedure_or_function procedure_or_function_name opt_owner_clause opt_comment_spec); PT_NODE *node = parser_new_node (this_parser, PT_ALTER_STORED_PROCEDURE); @@ -4096,6 +4155,7 @@ alter_stmt node->info.sp.type = ($2 == 1) ? PT_SP_PROCEDURE : PT_SP_FUNCTION; node->info.sp.ret_type = PT_TYPE_NONE; node->info.sp.owner = $4; + node->info.sp.recompile = 0; node->info.sp.comment = $5; if ($4 == NULL && $5 == NULL) { @@ -4108,6 +4168,26 @@ alter_stmt $$ = node; PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + DBG_PRINT}} + | ALTER /* 1 */ + procedure_or_function /* 2 */ + procedure_or_function_name /* 3 */ + COMPILE /* 4 */ + {{ DBG_TRACE_GRAMMAR(alter_stmt, | ALTER procedure_or_function procedure_or_function_name COMPILE); + + PT_NODE *node = parser_new_node (this_parser, PT_ALTER_STORED_PROCEDURE); + + if (node != NULL) + { + node->info.sp.name = $3; + node->info.sp.type = ($2 == 1) ? PT_SP_PROCEDURE : PT_SP_FUNCTION; + node->info.sp.ret_type = PT_TYPE_NONE; + node->info.sp.recompile = 1; + } + + $$ = node; + PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + DBG_PRINT}} | ALTER SERVER dblink_server_name alter_server_list {{ DBG_TRACE_GRAMMAR(alter_stmt, | ALTER SERVER dblink_server_name alter_server_list); @@ -4662,8 +4742,8 @@ drop_stmt PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) DBG_PRINT}} - | DROP PROCEDURE identifier_list - {{ DBG_TRACE_GRAMMAR(drop_stmt, | DROP PROCEDURE identifier_list); + | DROP PROCEDURE procedure_or_function_name_list + {{ DBG_TRACE_GRAMMAR(drop_stmt, | DROP PROCEDURE procedure_or_function_name_list); PT_NODE *node = parser_new_node (this_parser, PT_DROP_STORED_PROCEDURE); @@ -4678,8 +4758,8 @@ drop_stmt PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) DBG_PRINT}} - | DROP FUNCTION identifier_list - {{ DBG_TRACE_GRAMMAR(drop_stmt, | DROP FUNCTION identifier_list); + | DROP FUNCTION procedure_or_function_name_list + {{ DBG_TRACE_GRAMMAR(drop_stmt, | DROP FUNCTION procedure_or_function_name_list); PT_NODE *node = parser_new_node (this_parser, PT_DROP_STORED_PROCEDURE); @@ -5873,6 +5953,37 @@ synonym_name } ; +procedure_or_function_name_without_dot + : user_specified_name_without_dot + { DBG_TRACE_GRAMMAR(procedure_or_function_name_without_dot, : user_specified_name_without_dot); + $$ = $1; + } + ; + +procedure_or_function_name + : user_specified_name + { DBG_TRACE_GRAMMAR(procedure_or_function_name, : user_specified_name); + $$ = $1; + } + ; + +procedure_or_function_name_list + : procedure_or_function_name_list ',' procedure_or_function_name + {{ DBG_TRACE_GRAMMAR(procedure_or_function_name_list, : procedure_or_function_name_list ',' procedure_or_function_name); + + $$ = parser_make_link($1, $3); + PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + + DBG_PRINT}} + | procedure_or_function_name + {{ DBG_TRACE_GRAMMAR(procedure_or_function_name_list, : procedure_or_function_name); + + $$ = $1; + PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + + DBG_PRINT}} + ; + opt_partition_spec : /* empty */ {{ DBG_TRACE_GRAMMAR(opt_partition_spec, : ); @@ -8866,6 +8977,22 @@ auth_stmt $$ = node; PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + DBG_PRINT}} + | revoke_proc_cmd procedure_or_function_name_list from_id_list + {{ DBG_TRACE_GRAMMAR(auth_stmt, | revoke_proc_cmd procedure_or_function_name_list from_id_list); + + PT_NODE *node = parser_new_node (this_parser, PT_REVOKE); + + if (node) + { + node->info.revoke.user_list = $3; + node->info.revoke.spec_list = $2; + node->info.revoke.auth_cmd_list = $1; + } + + $$ = node; + PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + DBG_PRINT}} ; @@ -8885,6 +9012,23 @@ grant_cmd { pop_msg(); } { DBG_TRACE_GRAMMAR(grant_cmd, : GRANT author_cmd_list); $$ = $3; } + +grant_proc_cmd + : GRANT + { push_msg(MSGCAT_SYNTAX_MISSING_AUTH_COMMAND_LIST); } + authorized_execute_procedure_cmd + { pop_msg(); } + { DBG_TRACE_GRAMMAR(grant_proc_cmd, : GRANT authorized_execute_procedure_cmd); + $$ = $3; } + ; + +revoke_proc_cmd + : REVOKE + { push_msg(MSGCAT_SYNTAX_MISSING_AUTH_COMMAND_LIST); } + authorized_execute_procedure_cmd + { pop_msg(); } + { DBG_TRACE_GRAMMAR(revoke_proc_cmd, : REVOKE authorized_execute_procedure_cmd); + $$ = $3; } ; grant_head @@ -8919,6 +9063,38 @@ grant_head $$ = node; PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + DBG_PRINT}} + | grant_cmd to_id_list + {{ DBG_TRACE_GRAMMAR(grant_head, | grant_cmd to_id_list); + + PT_NODE *node = parser_new_node (this_parser, PT_GRANT); + + if (node) + { + node->info.grant.user_list = $2; + node->info.grant.spec_list = NULL; + node->info.grant.auth_cmd_list = $1; + } + + $$ = node; + PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + + DBG_PRINT}} + | grant_proc_cmd procedure_or_function_name_list to_id_list + {{ DBG_TRACE_GRAMMAR(grant_head, | grant_proc_cmd procedure_or_function_name_list to_id_list); + + PT_NODE *node = parser_new_node (this_parser, PT_GRANT); + + if (node) + { + node->info.grant.user_list = $3; + node->info.grant.spec_list = $2; + node->info.grant.auth_cmd_list = $1; + } + + $$ = node; + PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + DBG_PRINT}} ; @@ -8981,6 +9157,20 @@ author_cmd_list DBG_PRINT}} ; +authorized_execute_procedure_cmd + : EXECUTE ON_ PROCEDURE + {{ + PT_NODE *node = parser_new_node (this_parser, PT_AUTH_CMD); + if (node) + { + node->info.auth_cmd.auth_cmd = PT_EXECUTE_PROCEDURE_PRIV; + node->info.auth_cmd.attr_mthd_list = NULL; + } + $$ = node; + PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) + DBG_PRINT }} + ; + authorized_cmd : SELECT {{ DBG_TRACE_GRAMMAR(authorized_cmd, : SELECT); @@ -9116,6 +9306,7 @@ authorized_cmd PARSER_SAVE_ERR_CONTEXT ($$, @$.buffer_pos) DBG_PRINT}} + | EXECUTE {{ DBG_TRACE_GRAMMAR(authorized_cmd, | EXECUTE); @@ -12640,6 +12831,19 @@ sp_return_type DBG_PRINT}} ; +opt_authid + : /* empty */ + {{ $$ = PT_AUTHID_OWNER; }} + | AUTHID DEFINER + {{ $$ = PT_AUTHID_OWNER; }} + | AUTHID OWNER + {{ $$ = PT_AUTHID_OWNER; }} + | AUTHID CALLER + {{ $$ = PT_AUTHID_CALLER; }} + | AUTHID CURRENT_USER + {{ $$ = PT_AUTHID_CALLER; }} + ; + is_or_as : IS | AS @@ -12651,26 +12855,20 @@ opt_lang_plcsql ; pl_language_spec - : opt_lang_plcsql plcsql_text opt_identifier + : opt_lang_plcsql plcsql_text {{ DBG_TRACE_GRAMMAR(pl_language_spec, : opt_lang_plcsql plcsql_text); PT_NODE *node = parser_new_node (this_parser, PT_SP_BODY); if (node) { - int len; - - assert(g_plcsql_text != NULL); - - if ($3) { - len = $2 + strlen($3->info.name.original); - parser_free_tree(this_parser, $3); + node->info.sp_body.lang = SP_LANG_PLCSQL; + if (g_query_string) { + node->info.sp_body.impl = pt_create_string_literal_node_w_charset_coll( + g_query_string + g_plcsql_text_pos, $2); } else { - len = $2; + node->info.sp_body.impl = NULL; // set later } - - node->info.sp_body.lang = SP_LANG_PLCSQL; - node->info.sp_body.impl = pt_create_string_literal_node_w_charset_coll(g_plcsql_text, len); node->info.sp_body.direct = 1; } @@ -12707,9 +12905,9 @@ plcsql_text | plcsql_text_part {{ DBG_TRACE_GRAMMAR(plcsql_text, | plcsql_text_part); - assert(g_plcsql_text == NULL); + assert(g_plcsql_text_pos == -1); $$ = strlen($1); - g_plcsql_text = g_query_string + @$.buffer_pos - $$; + g_plcsql_text_pos = @$.buffer_pos - $$; DBG_PRINT}} ; @@ -12792,6 +12990,7 @@ sp_param_def : identifier opt_sp_in_out sp_param_type + opt_sp_default_value opt_comment_spec {{ DBG_TRACE_GRAMMAR(sp_param_def, : identifier opt_sp_in_out sp_param_type opt_comment_spec); @@ -12803,7 +13002,8 @@ sp_param_def node->data_type = CONTAINER_AT_1 ($3); node->info.sp_param.name = $1; node->info.sp_param.mode = $2; - node->info.sp_param.comment = $4; + node->info.sp_param.default_value = $4; + node->info.sp_param.comment = $5; } $$ = node; @@ -12883,6 +13083,26 @@ opt_sp_in_out DBG_PRINT}} ; +opt_sp_default_value + : /* empty */ + {{ + $$ = NULL; + DBG_PRINT}} + | DEFAULT + expression_ + {{ + PT_NODE *node = pt_make_data_default_expr_node (this_parser, $2); + PARSER_SAVE_ERR_CONTEXT (node, @2.buffer_pos) + $$ = node; + DBG_PRINT}} + | VAR_ASSIGN + expression_ + {{ + PT_NODE *node = pt_make_data_default_expr_node (this_parser, $2); + PARSER_SAVE_ERR_CONTEXT (node, @2.buffer_pos) + $$ = node; + DBG_PRINT}} + esql_query_stmt : { parser_select_level++; } csql_query_select_has_no_with_clause @@ -19286,7 +19506,7 @@ generic_function ; generic_function_for_call - : identifier + : procedure_or_function_name { if(pwd_info.parser_call_check) { @@ -19301,8 +19521,7 @@ generic_function_for_call } } '(' opt_expression_list_for_call ')' opt_on_target - {{ DBG_TRACE_GRAMMAR(generic_function_for_call, : identifier '(' opt_expression_list ')' opt_on_target ); - + {{ DBG_TRACE_GRAMMAR(generic_function_for_call, : procedure_or_function_name '(' opt_expression_list_for_call ')' opt_on_target ); PT_NODE *node = NULL; if ($6 == NULL) @@ -19319,6 +19538,17 @@ generic_function_for_call node->info.method_call.method_name = $1; node->info.method_call.arg_list = $4; node->info.method_call.on_call_target = $6; + if (node->info.method_call.on_call_target != NULL) + { + PT_NAME_INFO_CLEAR_FLAG (node->info.method_call.method_name, PT_NAME_INFO_USER_SPECIFIED); + } + else + { + if (node->info.method_call.arg_list != NULL && node->info.method_call.arg_list->node_type == PT_NAME && node->info.method_call.arg_list->info.name.meta_class == PT_META_CLASS) + { + PT_NAME_INFO_CLEAR_FLAG (node->info.method_call.method_name, PT_NAME_INFO_USER_SPECIFIED); + } + } node->info.method_call.call_or_expr = PT_IS_MTHD_EXPR; } @@ -22956,12 +23186,14 @@ identifier | ANALYZE {{ DBG_TRACE_GRAMMAR(identifier, | ANALYZE ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | ARCHIVE {{ DBG_TRACE_GRAMMAR(identifier, | ARCHIVE ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | ARIA {{ DBG_TRACE_GRAMMAR(identifier, | ARIA ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} + | AUTHID {{ DBG_TRACE_GRAMMAR(identifier, | AUTHID ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | AUTO_INCREMENT {{ DBG_TRACE_GRAMMAR(identifier, | AUTO_INCREMENT ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} - | BENCHMARK {{ DBG_TRACE_GRAMMAR(identifier, | BENCHMARK ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} + | BENCHMARK {{ DBG_TRACE_GRAMMAR(identifier, | BENCHMARK ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | BIT_AND {{ DBG_TRACE_GRAMMAR(identifier, | BIT_AND ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | BIT_OR {{ DBG_TRACE_GRAMMAR(identifier, | BIT_OR ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | BIT_XOR {{ DBG_TRACE_GRAMMAR(identifier, | BIT_XOR ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | BUFFER {{ DBG_TRACE_GRAMMAR(identifier, | BUFFER ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} + | CALLER {{ DBG_TRACE_GRAMMAR(identifier, | CALLER ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | CACHE {{ DBG_TRACE_GRAMMAR(identifier, | CACHE ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | CAPACITY {{ DBG_TRACE_GRAMMAR(identifier, | CAPACITY ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | CHARACTER_SET_ {{ DBG_TRACE_GRAMMAR(identifier, | CHARACTER_SET_ ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} @@ -22973,6 +23205,7 @@ identifier | COLUMNS {{ DBG_TRACE_GRAMMAR(identifier, | COLUMNS ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | COMMENT {{ DBG_TRACE_GRAMMAR(identifier, | COMMENT ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | COMMITTED {{ DBG_TRACE_GRAMMAR(identifier, | COMMITTED ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} + | COMPILE {{ DBG_TRACE_GRAMMAR(identifier, | COMPILE ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | COST {{ DBG_TRACE_GRAMMAR(identifier, | COST ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | CRITICAL {{ DBG_TRACE_GRAMMAR(identifier, | CRITICAL ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | CUME_DIST {{ DBG_TRACE_GRAMMAR(identifier, | CUME_DIST ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} @@ -22981,6 +23214,7 @@ identifier | DBLINK {{ DBG_TRACE_GRAMMAR(identifier, | DBLINK ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | DBNAME {{ DBG_TRACE_GRAMMAR(identifier, | DBNAME ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | DECREMENT {{ DBG_TRACE_GRAMMAR(identifier, | DECREMENT ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} + | DEFINER {{ DBG_TRACE_GRAMMAR(identifier, | DEFINER ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | DEDUPLICATE_ {{ DBG_TRACE_GRAMMAR(identifier, | DEDUPLICATE_ ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | DENSE_RANK {{ DBG_TRACE_GRAMMAR(identifier, | DENSE_RANK ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | DISK_SIZE {{ DBG_TRACE_GRAMMAR(identifier, | DISK_SIZE ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} @@ -23090,6 +23324,7 @@ identifier | QUEUES {{ DBG_TRACE_GRAMMAR(identifier, | QUEUES ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | RANGE_ {{ DBG_TRACE_GRAMMAR(identifier, | RANGE_ ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | RANK {{ DBG_TRACE_GRAMMAR(identifier, | RANK ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} + | REBUILD {{ DBG_TRACE_GRAMMAR(identifier, | REBUILD ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | REGEXP_COUNT {{ DBG_TRACE_GRAMMAR(identifier, | REGEXP_COUNT ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | REGEXP_INSTR {{ DBG_TRACE_GRAMMAR(identifier, | REGEXP_INSTR ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} | REGEXP_LIKE {{ DBG_TRACE_GRAMMAR(identifier, | REGEXP_LIKE ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }} @@ -26255,7 +26490,7 @@ parser_main (PARSER_CONTEXT * parser) { long desc_index = 0; long i, top; - int rv; + int rv, yybuffer_pos_save; PARSER_CONTEXT *this_parser_saved; @@ -26271,6 +26506,7 @@ parser_main (PARSER_CONTEXT * parser) dbcs_start_input (); yycolumn = yycolumn_end = 1; + yybuffer_pos_save = yybuffer_pos; yybuffer_pos=0; is_dblink_query_string = 0; expecting_pl_lang_spec = 0; @@ -26282,6 +26518,11 @@ parser_main (PARSER_CONTEXT * parser) pt_initialize_hint(parser, parser_hint_table); rv = yyparse (); + + // parser_main can be reentered while executing statements loaded by loaddb -s. + // During the loaddb -s, the yybuffer_pos must not be currupted. + yybuffer_pos = yybuffer_pos_save; + pt_cleanup_hint (parser, parser_hint_table); if (pt_has_error (parser) || parser->stack_top <= 0 || !parser->node_stack) @@ -26365,6 +26606,9 @@ parse_one_statement (int state) csql_yyset_lineno (1); yycolumn = yycolumn_end = 1; + // init only for the first time in order to make csql_yylloc.buffer_pos identical to the file pos + yybuffer_pos=0; + return 0; } @@ -26372,7 +26616,6 @@ parse_one_statement (int state) parser_yyinput_single_mode = 1; - yybuffer_pos=0; is_dblink_query_string = 0; expecting_pl_lang_spec = 0; csql_yylloc.buffer_pos=0; @@ -26390,8 +26633,7 @@ parse_one_statement (int state) else parser_statement_OK = 1; - if (!parser_yyinput_single_mode) /* eof */ - return 1; + parser_yyinput_single_mode = 0; return 0; } @@ -28446,3 +28688,50 @@ pt_add_password_offset (int start, int end, bool is_add_comma, EN_ADD_PWD_STRING password_add_offset (&this_parser->hide_pwd_info, start, end, is_add_comma, en_add_pwd_string); } + +static int +pt_set_plcsql_body_impl(PT_NODE* node, PT_NODE* body, int start, int spec_start, int spec_end, int end) +{ + // In (at least) following two cases, the control reaches here. + // . csql -i --no-single-line ... + // . cubrid loaddb -s ... + + // In these cases, parser->original_buffer is null and + // node->sql_user_text must be got from this_parser->file. + // The arguments start, spec_start, spec_end, and end are got from the tokens' buffer_pos + // but they are also actual positions in the file in these two cases. + + int r, read_sz = end - start; // texts from pos start to pos (end - 1) + char* buff = (char*) parser_alloc(this_parser, read_sz + 1); + + int file_pos = ftell(this_parser->file); + + r = fseek(this_parser->file, start, SEEK_SET); + if (r != 0) { + return -1; + } + + r = (int) fread(buff, 1, read_sz, this_parser->file); + if (r != read_sz) { + return -1; + } + + r = fseek(this_parser->file, file_pos, SEEK_SET); // restore it to the original position + if (r != 0){ + return -1; + } + + if (strncasecmp("create", buff, 6) != 0) { + return -1; + } + + buff[read_sz] = '\0'; + char* impl = buff + (spec_start - start); + + node->sql_user_text = buff; + node->sql_user_text_len = read_sz; + + body->info.sp_body.impl = pt_create_string_literal_node_w_charset_coll(impl, (spec_end - spec_start)); + + return 0; +} diff --git a/src/parser/csql_lexer.l b/src/parser/csql_lexer.l index 350e7e3f358..55c0b4505d1 100644 --- a/src/parser/csql_lexer.l +++ b/src/parser/csql_lexer.l @@ -38,8 +38,8 @@ #define CSQL_MAXNAME 256 -static int parser_yyinput_single_line (char *buff, int max_size); -static int parser_yyinput_multi_line (char *buff, int max_size); +int parser_yyinput_single_mode = 0; + static int parser_yyinput (char *buff, int max_size); static char *parser_c_hint (void); static char *parser_line_hint (void); @@ -94,6 +94,7 @@ int expecting_pl_lang_spec = 0; %x POST_DOT_OR_RIGHT_ARROW_STRING %x PL_LANG_SPEC %x PLCSQL_TEXT +%x POST_PLCSQL_TEXT /* id letter */ IDL [a-zA-Z0-9_] @@ -155,6 +156,7 @@ IDL [a-zA-Z0-9_] csql_yylval.cptr = pt_makename(yytext); return AUTO_INCREMENT; } [aA][vV][gG] { begin_token(yytext); return AVG; } +[aA][uU][tT][hH][iI][dD] { begin_token(yytext); csql_yylval.cptr = pt_makename(yytext); return AUTHID; } [bB][eE][fF][oO][rR][eE] { begin_token(yytext); return BEFORE; } [bB][eE][gG][iI][nN] { begin_token(yytext); return BEGIN_; } [bB][eE][nN][cC][hH][mM][aA][rR][kK] { begin_token(yytext); @@ -183,6 +185,7 @@ IDL [a-zA-Z0-9_] csql_yylval.cptr = pt_makename(yytext); return BUFFER; } [cC][aA][lL][lL] { begin_token(yytext); return CALL; } +[cC][aA][lL][lL][eE][rR] { begin_token(yytext); csql_yylval.cptr = pt_makename(yytext); return CALLER; } [cC][aA][cC][hH][eE] { begin_token(yytext); csql_yylval.cptr = pt_makename(yytext); return CACHE; } @@ -230,7 +233,10 @@ IDL [a-zA-Z0-9_] [cC][oO][mM][mM][iI][tT] { begin_token(yytext); return COMMIT; } [cC][oO][mM][mM][iI][tT][tT][eE][dD] { begin_token(yytext); csql_yylval.cptr = pt_makename(yytext); - return COMMITTED; } + return COMMITTED; } +[cC][oO][mM][pP][iI][lL][eE] { begin_token(yytext); + csql_yylval.cptr = pt_makename(yytext); + return COMPILE; } [cC][oO][nN][nN][eE][cC][tT] { begin_token(yytext); return CONNECT; } [cC][oO][nN][nN][eE][cC][tT][_][bB][yY][_][iI][sS][cC][yY][cC][lL][eE] { begin_token(yytext); return CONNECT_BY_ISCYCLE; } [cC][oO][nN][nN][eE][cC][tT][_][bB][yY][_][iI][sS][lL][eE][aA][fF] { begin_token(yytext); return CONNECT_BY_ISLEAF; } @@ -300,6 +306,7 @@ IDL [a-zA-Z0-9_] [dD][eE][fF][aA][uU][lL][tT] { begin_token(yytext); return DEFAULT; } [dD][eE][fF][eE][rR][rR][aA][bB][lL][eE] { begin_token(yytext); return DEFERRABLE; } [dD][eE][fF][eE][rR][rR][eE][dD] { begin_token(yytext); return DEFERRED; } +[dD][eE][fF][iI][nN][eE][rR] { begin_token(yytext); csql_yylval.cptr = pt_makename(yytext); return DEFINER; } [dD][eE][lL][eE][tT][eE] { begin_token(yytext); return DELETE_; } [dD][eE][nN][sS][eE]_[rR][aA][nN][kK] { begin_token(yytext); csql_yylval.cptr = pt_makename(yytext); @@ -795,7 +802,9 @@ IDL [a-zA-Z0-9_] return RANGE_; } [rR][eE][aA][dD] { begin_token(yytext); return READ; } [rR][eE][aA][lL] { begin_token(yytext); return FLOAT_; } -[rR][eE][bB][uU][iI][lL][dD] { begin_token(yytext); return REBUILD; } +[rR][eE][bB][uU][iI][lL][dD] { begin_token(yytext); + csql_yylval.cptr = pt_makename(yytext); + return REBUILD; } [rR][eE][cC][uU][rR][sS][iI][vV][eE] { begin_token(yytext); return RECURSIVE; } [rR][eE][fF] { begin_token(yytext); return REF; } [rR][eE][fF][eE][rR][eE][nN][cC][eE][sS] { begin_token(yytext); return REFERENCES; } @@ -1086,6 +1095,19 @@ IDL [a-zA-Z0-9_] \\N { begin_token(yytext); return Null; } +";" { begin_token(yytext); + if (parser_yyinput_single_mode) { + // Pretend to be an EOF + // to make yyparse() return. + // (parse a single statement at a time) + // NOTE: at the next call to yylex(), + // the work starts at the last state of + // the lexer. + return 0; + } else { + return SEMICOLON; + } + } "->" { begin_token(yytext); return RIGHT_ARROW; } "." { begin_token(yytext); return DOT; } "->>" { begin_token(yytext); return DOUBLE_RIGHT_ARROW; } @@ -1667,9 +1689,9 @@ _[uU][tT][fF]8['] { plcsql_begin_end_balance++; csql_yylval.cptr = pt_makename(yytext); return PLCSQL_TEXT_SOME; } -[eE][nN][dD][ \t\r\n]+[iI][fF] | -[eE][nN][dD][ \t\r\n]+[cC][aA][sS][eE] | -[eE][nN][dD][ \t\r\n]+[lL][oO][oO][pP] | +[eE][nN][dD][ \t\r\n]+[iI][fF][ \t\r\n]* | +[eE][nN][dD][ \t\r\n]+[cC][aA][sS][eE][ \t\r\n]* | +[eE][nN][dD][ \t\r\n]+[lL][oO][oO][pP][ \t\r\n]* | [eE][nN][dD][ \t\r\n]* { begin_token(yytext); plcsql_begin_end_balance--; if (plcsql_begin_end_balance < 0) { @@ -1680,7 +1702,7 @@ _[uU][tT][fF]8['] { if (plcsql_begin_end_balance == 0) { plcsql_nest_level--; if (plcsql_nest_level < 0) { - BEGIN(INITIAL); + BEGIN(POST_PLCSQL_TEXT); } } csql_yylval.cptr = pt_makename(yytext); @@ -1709,10 +1731,25 @@ _[uU][tT][fF]8['] { csql_yylval.cptr = pt_makename(yytext); return PLCSQL_TEXT_SOME; } + /* mode POST_PLCSQL_TEXT */ -%% +[cC][oO][mM][mM][eE][nN][tT] { BEGIN(INITIAL); + yybuffer_pos -= csql_yyleng; + yyless(0); } -int parser_yyinput_single_mode = 0; +{IDL}+ { BEGIN(INITIAL); + begin_token(yytext); + csql_yylval.cptr = pt_makename(yytext); + return PLCSQL_TEXT_SOME; } + +(.) { BEGIN(INITIAL); + yybuffer_pos -= csql_yyleng; + yyless(0); } + +<> { BEGIN(INITIAL); + return 0; } + +%% void csql_yyerror_explicit (int line, int column) @@ -1964,9 +2001,9 @@ yywrap () static void init_plcsql_lexing() { - plcsql_begin_end_balance = 0; - plcsql_nest_level = 0; - from_plcsql_text = 0; + plcsql_begin_end_balance = 0; + plcsql_nest_level = 0; + from_plcsql_text = 0; } static int @@ -2030,24 +2067,25 @@ parser_yyinput_single_line (char *buff, int max_size) while (c != -1); } + buff[i++] = c; + if (c == ';') { - buff[i++] = -1; - buff[i] = 0; + buff[i] = '\0'; /* not required but to ease debugging */ + /* stop filling the buffer. see PR 5403 */ return i; } - buff[i++] = c; if (i >= max_size) { + buff[i] = '\0'; /* not required but to ease debugging */ return i; } } while (c != -1); - buff[i] = 0; - parser_yyinput_single_mode = 0; /* all done */ + buff[i] = '\0'; /* not required but to ease debugging */ /* end of file */ str_identifier = '\0'; diff --git a/src/parser/keyword.c b/src/parser/keyword.c index 8771d4a4215..9ec4b880dfb 100644 --- a/src/parser/keyword.c +++ b/src/parser/keyword.c @@ -63,6 +63,7 @@ static KEYWORD_RECORD keywords[] = { {AT, "AT", 0}, {ATTACH, "ATTACH", 0}, {ATTRIBUTE, "ATTRIBUTE", 0}, + {AUTHID, "AUTHID", 1}, {AUTO_INCREMENT, "AUTO_INCREMENT", 1}, {AVG, "AVG", 0}, {BEFORE, "BEFORE", 0}, @@ -82,6 +83,7 @@ static KEYWORD_RECORD keywords[] = { {BY, "BY", 0}, {BUFFER, "BUFFER", 1}, {CALL, "CALL", 0}, + {CALLER, "CALLER", 1}, {CACHE, "CACHE", 1}, {CAPACITY, "CAPACITY", 1}, {CASCADE, "CASCADE", 0}, @@ -145,6 +147,7 @@ static KEYWORD_RECORD keywords[] = { {DAY_SECOND, "DAY_SECOND", 0}, {DBLINK, "DBLINK", 0}, {DEALLOCATE, "DEALLOCATE", 0}, + {DEFINER, "DEFINER", 1}, {NUMERIC, "DEC", 0}, {NUMERIC, "DECIMAL", 0}, {DECLARE, "DECLARE", 0}, diff --git a/src/parser/method_transform.c b/src/parser/method_transform.c index 8d40ea3e959..ee7b7f4bf7d 100644 --- a/src/parser/method_transform.c +++ b/src/parser/method_transform.c @@ -184,7 +184,7 @@ meth_have_methods (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *cont int *have_method = (int *) arg; *continue_walk = PT_CONTINUE_WALK; - if (node->node_type == PT_METHOD_CALL) + if (PT_IS_METHOD (node)) { *have_method = 1; *continue_walk = PT_STOP_WALK; @@ -465,14 +465,14 @@ meth_create_method_list (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg *continue_walk = PT_LIST_WALK; } - if (node->node_type == PT_DOT_ && (arg1 = node->info.dot.arg1) && arg1->node_type == PT_METHOD_CALL + if (node->node_type == PT_DOT_ && (arg1 = node->info.dot.arg1) && PT_IS_METHOD (arg1) && arg1->info.method_call.call_or_expr == PT_PARAMETER && node->info.dot.arg2) { /* this is a path expression rooted in a constant method call. We need to tag it as such for xasl generation */ node->info.dot.arg2->info.name.meta_class = PT_PARAMETER; } - if ((node->node_type != PT_METHOD_CALL) || (node->info.method_call.method_name->info.name.spec_id == 0)) + if (!PT_IS_METHOD (node) || (node->info.method_call.method_name->info.name.spec_id == 0)) { return node; } @@ -1083,7 +1083,7 @@ meth_get_method_params (PARSER_CONTEXT * parser, UINTPTR spec_id, PT_NODE * meth for (method = method_list; method != NULL; method = method->next) { - if (method->node_type != PT_METHOD_CALL) + if (!PT_IS_METHOD (method)) { PT_INTERNAL_ERROR (parser, "translate"); return NULL; @@ -1199,7 +1199,7 @@ meth_replace_method_params (PARSER_CONTEXT * parser, UINTPTR spec_id, PT_NODE * attr_list = as_attr_list; for (method = method_list; method != NULL; method = method->next) { - if (method->node_type != PT_METHOD_CALL) + if (!PT_IS_METHOD (method)) { PT_INTERNAL_ERROR (parser, "translate"); return; @@ -1285,7 +1285,7 @@ meth_replace_method_calls (PARSER_CONTEXT * parser, PT_NODE * root, PT_NODE * me attr_list = as_attr_list; for (method = method_list; method != NULL; method = method->next) { - if (method->node_type != PT_METHOD_CALL) + if (!PT_IS_METHOD (method)) { PT_INTERNAL_ERROR (parser, "translate"); return; @@ -1314,7 +1314,7 @@ meth_replace_call (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int PT_NODE *new_node; METH_INFO1 info; - if (node->node_type != PT_METHOD_CALL) + if (!PT_IS_METHOD (node)) { return node; } @@ -1421,8 +1421,7 @@ meth_find_last_entity (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, } /* don't walk into the method you're checking with */ - if (node->node_type == PT_METHOD_CALL - && (node->info.method_call.method_id == info->method->info.method_call.method_id)) + if (PT_IS_METHOD (node) && (node->info.method_call.method_id == info->method->info.method_call.method_id)) { *continue_walk = PT_LIST_WALK; } @@ -1501,7 +1500,7 @@ meth_match_entity (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int /* check to see if we want to dive into nested method calls. don't dive into data type nodes */ - if ((!info7->check_method_calls && (node->node_type == PT_METHOD_CALL)) || (node->node_type == PT_DATA_TYPE)) + if (!info7->check_method_calls && (PT_IS_METHOD (node) || (node->node_type == PT_DATA_TYPE))) { *continue_walk = PT_LIST_WALK; return node; @@ -1817,7 +1816,7 @@ meth_is_method (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int *co *continue_walk = PT_CONTINUE_WALK; - if (node->node_type == PT_METHOD_CALL && node->info.method_call.call_or_expr != PT_PARAMETER) + if (PT_IS_METHOD (node) && node->info.method_call.call_or_expr != PT_PARAMETER) { *is_a_method = 1; } @@ -1931,7 +1930,7 @@ meth_find_method (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int * *continue_walk = PT_CONTINUE_WALK; - if (node->node_type == PT_METHOD_CALL && (info->id == 0 || node->info.method_call.method_id == info->id)) + if (PT_IS_METHOD (node) && (info->id == 0 || node->info.method_call.method_id == info->id)) { info->found = 1; } @@ -2279,7 +2278,7 @@ meth_replace_id_in_method_names (PARSER_CONTEXT * parser, PT_NODE * node, void * { METH_INFO6 *info6 = (METH_INFO6 *) void_arg; - if (node->node_type == PT_METHOD_CALL && (node->info.method_call.method_name->info.name.spec_id == info6->old_id)) + if (PT_IS_METHOD (node) && (node->info.method_call.method_name->info.name.spec_id == info6->old_id)) { node->info.method_call.method_name->info.name.spec_id = info6->new_id; } @@ -2362,7 +2361,7 @@ meth_find_hierarchical_in_method_list (PARSER_CONTEXT * parser, PT_NODE * method for (node = method_list; node != NULL && !(*has_hierarchical_expr); node = node->next) { - if (node->node_type == PT_METHOD_CALL) + if (PT_IS_METHOD (node)) { for (arg = node->info.method_call.arg_list; arg != NULL && !(*has_hierarchical_expr); arg = arg->next) { diff --git a/src/parser/name_resolution.c b/src/parser/name_resolution.c index 5eca7113933..6944d1eda6b 100644 --- a/src/parser/name_resolution.c +++ b/src/parser/name_resolution.c @@ -530,6 +530,10 @@ pt_resolved (const PT_NODE * expr) return (expr->info.name.spec_id != 0); case PT_DOT_: return (pt_resolved (expr->info.dot.arg1) && pt_resolved (expr->info.dot.arg2)); + case PT_FUNCTION: + // Resolved as a function node. + // If it's actually a user-defined function, this node will be resolved in the next phase (function resolution). + return (expr->info.function.function_type == PT_GENERIC); default: break; } @@ -941,8 +945,9 @@ pt_bind_name_or_path_in_scope (PARSER_CONTEXT * parser, PT_BIND_NAMES_ARG * bind /* If pt_name in group by/ having, maybe it's alias. We will try to resolve it later. */ if (!is_pt_name_in_group_having (in_node)) { - - if (parser->flag.is_parsing_static_sql == 1) + if (parser->flag.is_parsing_static_sql == 1 + && ((in_node->node_type == PT_DOT_ && !pt_resolved (in_node->info.dot.arg2)) + || in_node->node_type == PT_NAME)) { // clear unknown attribute error, the unknown symbol will be converted (paramterized) to host variable pt_reset_error (parser); @@ -1980,6 +1985,8 @@ pt_bind_names (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue short i, k, lhs_location, rhs_location, level; PT_JOIN_TYPE join_type; void *save_etc = NULL; + PT_NODE *method_name_node = NULL; + const char *method_name; *continue_walk = PT_CONTINUE_WALK; @@ -3288,13 +3295,16 @@ pt_bind_names (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue * first parameter to the on_call_target. If there is no parameter, * it will be caught in pt_semantic_check_local() */ - if (!node->info.method_call.on_call_target - && jsp_is_exist_stored_procedure (node->info.method_call.method_name->info.name.original)) - { - PT_NODE *method_name = node->info.method_call.method_name; - node->info.method_call.method_name->info.name.spec_id = (UINTPTR) method_name; - node->info.method_call.method_type = (PT_MISC_TYPE) jsp_get_sp_type (method_name->info.name.original); - node->info.method_call.method_name->info.name.meta_class = PT_METHOD; + method_name_node = node->info.method_call.method_name; + // parser_print_tree is for built-in package names such as DBMS_OUTPUT + method_name = PT_NAME_RESOLVED (method_name_node) ? parser_print_tree (parser, + method_name_node) : + PT_NAME_ORIGINAL (method_name_node); + if (!node->info.method_call.on_call_target && jsp_is_exist_stored_procedure (method_name)) + { + method_name_node->info.name.spec_id = (UINTPTR) method_name_node; + node->info.method_call.method_type = (PT_MISC_TYPE) jsp_get_sp_type (method_name); + method_name_node->info.name.meta_class = PT_METHOD; parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg); /* don't revisit leaves */ *continue_walk = PT_LIST_WALK; @@ -3306,6 +3316,19 @@ pt_bind_names (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue node->info.method_call.on_call_target = node->info.method_call.arg_list; node->info.method_call.arg_list = node->info.method_call.arg_list->next; node->info.method_call.on_call_target->next = NULL; + + /* + * When using a session variable in the first arg_list, + * It is unknown whether the session variable contains a class, object, or constant value. + * So, if it's not a Java stored procedure and there is an on_call_target, then it's considered a method and [user_schema] is removed. + * + * ex) create class x (xint int, xstr string, class cint int) method add_int(int, int) int function add_int file '$METHOD_FILE'; + * insert into x values (4, 'string 4'); + * select x into p1 from x where xint = 4; + * call add_int(p1, 1, 2); + */ + node->info.method_call.method_name->info.name.original = + sm_remove_qualifier_name (node->info.method_call.method_name->info.name.original); } /* make method name look resolved */ @@ -3347,9 +3370,7 @@ pt_bind_names (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue node->info.method_call.method_name->info.name.spec_id = entity->info.spec.id; } } - } - break; case PT_DATA_TYPE: @@ -3406,6 +3427,44 @@ pt_bind_names (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue { node = temp; } + else if (PT_CHECK_USER_SCHEMA_PROCEDURE_OR_FUNCTION (node)) + { + /* + * when (dot.arg1->node_type == PT_NAME) && (dot.arg2->node_type == PT_FUNCTION), + * pt_bind_name_or_path_in_scope() always returns NULL and sets the value PT_ERRORmf(.. MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_IS_NOT_DEFINED ..). + */ + pt_reset_error (parser); + + /* + * jsp_is_exist_stored_procedure() could not be checked in pt_set_user_specified_name(), so it was checked in pt_bind_names(). + * Created a temporary node in name.original to join user_schema(dot.arg1) and sp_name(dot.arg2). + */ + char downcase_owner_name[DB_MAX_USER_LENGTH]; + downcase_owner_name[0] = '\0'; + char *generic_name = NULL; + + sm_downcase_name (node->info.dot.arg1->info.name.original, downcase_owner_name, DB_MAX_USER_LENGTH); + generic_name = pt_append_string (parser, downcase_owner_name, "."); + generic_name = pt_append_string (parser, generic_name, node->info.dot.arg2->info.function.generic_name); + node->info.dot.arg2->info.function.generic_name = generic_name; + node->info.dot.arg1->info.name.original = generic_name; + + if (jsp_is_exist_stored_procedure (node->info.dot.arg2->info.function.generic_name)) + { + node1 = pt_resolve_stored_procedure (parser, node->info.dot.arg2, bind_arg); + if (node1 == NULL) + { + break; // FIXME: something wrong + } + PT_NODE_COPY_NUMBER_OUTERLINK (node1, node); + + PT_NODE_INIT_OUTERLINK (node); + parser_free_tree (parser, node); + node = node1; /* return the new node */ + /* don't revisit leaves */ + *continue_walk = PT_LIST_WALK; + } + } else if (pt_has_error (parser)) { return NULL; @@ -3440,18 +3499,38 @@ pt_bind_names (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue case PT_FUNCTION: if (node->info.function.function_type == PT_GENERIC) { - const char *generic_name = node->info.function.generic_name; + MOP sp_mop = NULL; + char sp_unique_name[SM_MAX_IDENTIFIER_LENGTH + 1]; node->info.function.function_type = pt_find_function_type (node->info.function.generic_name); if (node->info.function.function_type == PT_GENERIC) { + if (strchr (node->info.function.generic_name, '.')) + { + /* + * when checking for a PROCEDURE in a PT_DOT_ type, if the PROCEDURE does not exist, the check moves on to the PT_FUNCTION. + * along the way, it will go through the pt_bind_name_or_path_in_scope() function of PT_NAME, + * which will always return NULL and set the value of + * PT_ERRORmf(.. MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_IS_NOT_DEFINED ..). + */ + pt_reset_error (parser); + } + /* * It may be a method call since they are parsed as * nodes PT_FUNCTION. If so, pt_make_stored_procedure() and pt_make_method_call() will * translate it into a method_call. */ - if (jsp_is_exist_stored_procedure (generic_name)) + sp_mop = jsp_find_stored_procedure (node->info.function.generic_name, DB_AUTH_NONE); + if (sp_mop != NULL) { + sp_unique_name[0] = '\0'; + jsp_get_unique_name (sp_mop, sp_unique_name, DB_MAX_IDENTIFIER_LENGTH + 1); + if (sp_unique_name[0] != '\0') + { + node->info.function.generic_name = pt_append_string (parser, NULL, sp_unique_name); + } + node1 = pt_resolve_stored_procedure (parser, node, bind_arg); } else @@ -3505,17 +3584,24 @@ pt_bind_names (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue PT_ERRORm (parser, node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_PREFIX_IN_FUNC_INDX_NOT_ALLOWED); } - else if (parser_function_code != PT_EMPTY) - { - PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC, - MSGCAT_SEMANTIC_INVALID_INTERNAL_FUNCTION, node->info.function.generic_name); - } else { - PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_UNKNOWN_FUNCTION, - node->info.function.generic_name); - } + char downcase_generic_name[DB_MAX_IDENTIFIER_LENGTH]; + downcase_generic_name[0] = '\0'; + sm_downcase_name (node->info.function.generic_name, downcase_generic_name, + DB_MAX_IDENTIFIER_LENGTH); + if (parser_function_code != PT_EMPTY) + { + PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC, + MSGCAT_SEMANTIC_INVALID_INTERNAL_FUNCTION, downcase_generic_name); + } + else + { + PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_UNKNOWN_FUNCTION, + downcase_generic_name); + } + } } } } @@ -10163,6 +10249,8 @@ pt_make_method_call (PARSER_CONTEXT * parser, PT_NODE * f_node, PT_BIND_NAMES_AR new_node->info.method_call.arg_list = parser_copy_tree_list (parser, f_node->info.function.arg_list); new_node->info.method_call.call_or_expr = PT_IS_MTHD_EXPR; new_node->info.method_call.on_call_target = NULL; + new_node->info.method_call.auth_name = NULL; + PT_METHOD_CALL_AUTH_NAME (new_node) = ws_copy_string (au_get_user_name (Au_user)); // default return new_node; } /* pt_make_method_call */ @@ -10257,6 +10345,10 @@ pt_resolve_method (PARSER_CONTEXT * parser, PT_NODE * node, PT_BIND_NAMES_ARG * static PT_NODE * pt_resolve_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * node, PT_BIND_NAMES_ARG * bind_arg) { + char owner[DB_MAX_USER_LENGTH + 1]; + owner[0] = '\0'; + char *current_user_owner; + PT_NODE *new_node = pt_make_method_call (parser, node, bind_arg); if (new_node == NULL) { @@ -10274,6 +10366,12 @@ pt_resolve_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * node, PT_BIND_NA return NULL; } + if (jsp_get_owner_name (sp_name, owner, DB_MAX_USER_LENGTH) == NULL) + { + PT_INTERNAL_ERROR (parser, "jsp_get_owner_name"); + return NULL; + } + new_node->type_enum = pt_db_to_type_enum ((DB_TYPE) return_type); TP_DOMAIN *d = pt_type_enum_to_db_domain (new_node->type_enum); d = tp_domain_cache (d); @@ -10284,6 +10382,18 @@ pt_resolve_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * node, PT_BIND_NA int sp_type_misc = jsp_get_sp_type (sp_name); new_node->info.method_call.method_type = (PT_MISC_TYPE) sp_type_misc; + PT_METHOD_CALL_AUTH_ID (new_node) = PT_AUTHID_OWNER; // TODO + if (PT_METHOD_CALL_AUTH_ID (new_node) == PT_AUTHID_OWNER) + { + PT_METHOD_CALL_AUTH_NAME (new_node) = pt_append_string (parser, NULL, owner); + } + else + { + current_user_owner = au_get_user_name (Au_user); + PT_METHOD_CALL_AUTH_NAME (new_node) = pt_append_string (parser, NULL, current_user_owner); + ws_free_string_and_init (current_user_owner); + } + return new_node; } /* pt_resolve_stored_procedure */ diff --git a/src/parser/parse_dbi.c b/src/parser/parse_dbi.c index dba3874b8a9..36a1c5802a2 100644 --- a/src/parser/parse_dbi.c +++ b/src/parser/parse_dbi.c @@ -2577,6 +2577,10 @@ pt_auth_to_db_auth (const PT_NODE * auth) db_auth = DB_AUTH_UPDATE; break; + case PT_EXECUTE_PROCEDURE_PRIV: + db_auth = DB_AUTH_EXECUTE; + break; + default: db_auth = DB_AUTH_NONE; break; diff --git a/src/parser/parse_evaluate.c b/src/parser/parse_evaluate.c index 4488b5efe77..de661ee47b9 100644 --- a/src/parser/parse_evaluate.c +++ b/src/parser/parse_evaluate.c @@ -1369,6 +1369,14 @@ pt_evaluate_tree_internal (PARSER_CONTEXT * parser, PT_NODE * tree, DB_VALUE * d break; case PT_METHOD_CALL: + + if (!PT_IS_METHOD (tree) + && !(tree->info.method_call.call_or_expr == PT_IS_CALL_STMT) && do_Trigger_involved == false) + { + // do not perform constant folding + break; + } + if (qo_need_skip_execution ()) { // It is for the get_query_info. diff --git a/src/parser/parse_tree.c b/src/parser/parse_tree.c index b9f4ec26414..190c738697c 100644 --- a/src/parser/parse_tree.c +++ b/src/parser/parse_tree.c @@ -1232,6 +1232,7 @@ parser_create_parser (void) parser->max_print_len = 0; parser->flag.is_auto_commit = 0; parser->flag.is_parsing_static_sql = 0; + parser->flag.is_parsing_unload_schema = 0; parser->external_into_label = NULL; parser->external_into_label_cnt = 0; diff --git a/src/parser/parse_tree.h b/src/parser/parse_tree.h index 57e22cc7895..bdc1e739ce0 100644 --- a/src/parser/parse_tree.h +++ b/src/parser/parse_tree.h @@ -114,6 +114,11 @@ struct json_t; #define PT_INTERNAL_ERROR(parser, what) \ pt_internal_error((parser), __FILE__, __LINE__, (what)) +// macros for PARSER_CONTEXT +#define PT_IS_FOR_PL_COMPILE(parser) \ + ((parser)->flag.is_parsing_static_sql == 1) + +// macros for PT_NODE */ #define PT_IS_QUERY_NODE_TYPE(x) \ ( (x) == PT_SELECT || (x) == PT_UNION \ || (x) == PT_DIFFERENCE || (x) == PT_INTERSECTION) @@ -262,6 +267,7 @@ struct json_t; #define pt_is_dot_node(n) PT_IS_DOT_NODE(n) #define pt_is_expr_node(n) PT_IS_EXPR_NODE(n) #define pt_is_function(n) PT_IS_FUNCTION(n) +#define pt_is_sp(n) PT_IS_SP(n) #define pt_is_multi_col_term(n) PT_IS_MULTI_COL_TERM(n) #define pt_is_name_node(n) PT_IS_NAME_NODE(n) #define pt_is_oid_name(n) PT_IS_OID_NAME(n) @@ -540,6 +546,12 @@ struct json_t; || (n->node_type == PT_UPDATE && n->info.update.spec->info.spec.remote_server_name) \ || (n->node_type == PT_MERGE && n->info.merge.into->info.spec.remote_server_name)) +#define PT_CHECK_USER_SCHEMA_PROCEDURE_OR_FUNCTION(n) \ + ((n->info.dot.arg1->node_type == PT_NAME) \ + && (n->info.dot.arg2->node_type == PT_FUNCTION) \ + && (n->info.dot.arg2->info.function.function_type == PT_GENERIC) \ + && (strchr (n->info.dot.arg2->info.function.generic_name, '.') == NULL)) + #if !defined (SERVER_MODE) /* the following defines support host variable binding for internal statements. internal statements can be generated on TEXT handling, and these statements @@ -751,7 +763,7 @@ struct json_t; ( (n) && (n)->node_type == PT_METHOD_CALL && \ (n)->info.method_call.method_type == PT_IS_INST_MTHD ) -#define PT_IS_JAVA_SP(n) \ +#define PT_IS_SP(n) \ ( (n) && (n)->node_type == PT_METHOD_CALL && \ ( (n)->info.method_call.method_type == PT_SP_PROCEDURE || \ (n)->info.method_call.method_type == PT_SP_FUNCTION) ) @@ -778,6 +790,7 @@ struct json_t; #define PT_NAME_ORIGINAL(n) (PT_NAME_ASSERT ((n)), (n)->info.name.original) #define PT_NAME_RESOLVED(n) (PT_NAME_ASSERT ((n)), (n)->info.name.resolved) #define PT_NAME_DB_OBJECT(n) (PT_NAME_ASSERT ((n)), (n)->info.name.db_object) +#define PT_NAME_ORIGINAL(n) (PT_NAME_ASSERT ((n)), (n)->info.name.original) /* PT_CREATE_ENTITY */ #define PT_CREATE_ENTITY_ASSERT(n) (PT_ASSERT_NODE_TYPE ((n), PT_CREATE_ENTITY)) @@ -820,6 +833,12 @@ struct json_t; #define PT_SYNONYM_IF_EXISTS(n) ((n)->info.synonym.if_exists) #define PT_SYNONYM_IS_DBLINKED(n) ((n)->info.synonym.is_dblinked) /* for user.table@server */ +/* PT_METHOD_CALL_INFO */ +#define PT_METHOD_CALL_NAME(n) ((n)->info.method_call.method_name) +#define PT_METHOD_ARG_LIST(n) ((n)->info.method_call.arg_list) +#define PT_METHOD_CALL_AUTH_ID(n) ((n)->info.method_call.auth_id) +#define PT_METHOD_CALL_AUTH_NAME(n) ((n)->info.method_call.auth_name) + /* Check node_type of PT_NODE */ #define PT_NODE_IS_EXPR(n) (PT_ASSERT_NOT_NULL ((n)), (n)->node_type == PT_EXPR) #define PT_NODE_IS_NAME(n) (PT_ASSERT_NOT_NULL ((n)), (n)->node_type == PT_NAME) @@ -1157,7 +1176,8 @@ typedef enum PT_INSERT_PRIV, PT_REFERENCES_PRIV, /* for ANSI compatibility */ PT_SELECT_PRIV, - PT_UPDATE_PRIV + PT_UPDATE_PRIV, + PT_EXECUTE_PROCEDURE_PRIV } PT_PRIV_TYPE; /* Enumerated Misc Types */ @@ -1327,7 +1347,10 @@ typedef enum PT_PRIVATE, PT_PUBLIC, - PT_SYNONYM + PT_SYNONYM, + + PT_AUTHID_OWNER, + PT_AUTHID_CALLER // todo: separate into relevant enumerations } PT_MISC_TYPE; @@ -2511,7 +2534,7 @@ struct pt_grant_info { PT_NODE *auth_cmd_list; /* PT_AUTH_CMD(list) */ PT_NODE *user_list; /* PT_NAME */ - PT_NODE *spec_list; /* PT_SPEC */ + PT_NODE *spec_list; /* PT_SPEC (class) or PT_NAME (procedure) */ PT_MISC_TYPE grant_option; /* = PT_GRANT_OPTION or PT_NO_GRANT_OPTION */ }; @@ -2576,6 +2599,8 @@ struct pt_method_call_info PT_NODE *to_return_var; /* PT_NAME */ PT_MISC_TYPE call_or_expr; /* PT_IS_CALL_STMT or PT_IS_MTHD_EXPR */ PT_MISC_TYPE method_type; /* PT_IS_CLASS_MTHD, PT_IS_INST_MTHD, PT_SP_PROCEDURE, PT_SP_FUNCTION */ + char *auth_name; /* owner or current user name */ + PT_MISC_TYPE auth_id; /* PT_AUTHID_OWNER, PT_AUTHID_CALLER */ UINTPTR method_id; /* unique identifier so when copying we know if two methods are copies of the same * original method call. */ }; @@ -3376,11 +3401,12 @@ struct pt_stored_proc_info PT_NODE *body; PT_NODE *comment; PT_NODE *owner; /* for ALTER PROCEDURE/FUNCTION name OWNER TO new_owner */ + PT_MISC_TYPE auth_id; /* PT_AUTHID_OWNER, PT_AUTHID_CALLER */ PT_MISC_TYPE type; unsigned or_replace:1; /* OR REPLACE clause */ PT_TYPE_ENUM ret_type; PT_NODE *ret_data_type; - + int recompile; }; struct pt_prepare_info @@ -3406,8 +3432,9 @@ struct pt_execute_info struct pt_stored_proc_param_info { - PT_NODE *name; - PT_MISC_TYPE mode; + PT_NODE *name; /* PT_NAME */ + PT_MISC_TYPE mode; /* PT_INPUT, PT_OUTPUT, PT_INPUTOUTPUT */ + PT_NODE *default_value; /* PT_DATA_DEFAULT */ PT_NODE *comment; }; @@ -3992,6 +4019,7 @@ struct parser_context unsigned is_system_generated_stmt:1; unsigned is_auto_commit:1; /* set to true, if auto commit. */ unsigned is_parsing_static_sql:1; /* For PL/CSQL's static SQL: parameterize PL/CSQL variable symbols (to host variable) */ + unsigned is_parsing_unload_schema:1; /* Parsing in unload: used to parse the scode (original query) of PL/CSQL to remove the owner. */ } flag; }; diff --git a/src/parser/parse_tree_cl.c b/src/parser/parse_tree_cl.c index 412d43d2c7d..fae8857f986 100644 --- a/src/parser/parse_tree_cl.c +++ b/src/parser/parse_tree_cl.c @@ -943,6 +943,13 @@ pt_walk_private (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg) * calling pt_apply. */ node_type = node->node_type; + assert (node_type >= PT_NODE_NONE); + if (node_type == PT_NODE_NONE) + { + assert (pt_has_error (parser)); + return NULL; + } + if (node_type >= PT_LAST_NODE_NUMBER || !(apply = pt_apply_f[node_type])) { return NULL; @@ -4043,6 +4050,8 @@ pt_show_priv (PT_PRIV_TYPE t) return "drop"; case PT_EXECUTE_PRIV: return "execute"; + case PT_EXECUTE_PROCEDURE_PRIV: + return "execute on procedure"; case PT_INDEX_PRIV: return "index"; case PT_INSERT_PRIV: @@ -7564,6 +7573,7 @@ pt_print_create_trigger (PARSER_CONTEXT * parser, PT_NODE * p) static PT_NODE * pt_apply_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * p, void *arg) { + PT_APPLY_WALK (parser, p->info.sp.name, arg); PT_APPLY_WALK (parser, p->info.sp.param_list, arg); PT_APPLY_WALK (parser, p->info.sp.ret_data_type, arg); return p; @@ -7580,6 +7590,7 @@ pt_apply_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * p, void *ar static PT_NODE * pt_apply_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * p, void *arg) { + PT_APPLY_WALK (parser, p->info.sp.name, arg); return p; } @@ -7595,14 +7606,26 @@ pt_print_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * p) PARSER_VARCHAR *q = NULL, *r1, *r2, *r3; r1 = pt_print_bytes (parser, p->info.sp.name); - q = pt_append_nulstring (parser, q, "create "); - if (p->info.sp.or_replace) + + q = pt_append_nulstring (parser, q, parser->flag.is_parsing_unload_schema ? "CREATE OR REPLACE " : "create "); + if (p->info.sp.or_replace && !parser->flag.is_parsing_unload_schema) { q = pt_append_nulstring (parser, q, "or replace "); } - q = pt_append_nulstring (parser, q, pt_show_misc_type (p->info.sp.type)); + q = + pt_append_nulstring (parser, q, + parser->flag.is_parsing_unload_schema ? strcmp (pt_show_misc_type (p->info.sp.type), + "procedure") == + 0 ? "PROCEDURE" : "FUNCTION" : pt_show_misc_type (p->info.sp.type)); q = pt_append_nulstring (parser, q, " "); - q = pt_append_varchar (parser, q, r1); + if (parser->custom_print & (PT_PRINT_NO_SPECIFIED_USER_NAME | PT_PRINT_NO_CURRENT_USER_NAME)) + { + q = pt_append_name (parser, q, p->info.sp.name->info.name.original); + } + else + { + q = pt_append_varchar (parser, q, r1); + } r2 = pt_print_bytes_l (parser, p->info.sp.param_list); q = pt_append_nulstring (parser, q, "("); @@ -7611,7 +7634,7 @@ pt_print_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * p) if (p->info.sp.type == PT_SP_FUNCTION) { - q = pt_append_nulstring (parser, q, " return "); + q = pt_append_nulstring (parser, q, parser->flag.is_parsing_unload_schema ? " RETURN " : " return "); if (p->info.sp.ret_data_type) { q = pt_append_varchar (parser, q, pt_print_bytes (parser, p->info.sp.ret_data_type)); @@ -7622,10 +7645,22 @@ pt_print_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * p) } } + if (parser->flag.is_parsing_unload_schema) + { + if (p->info.sp.auth_id == PT_AUTHID_OWNER) + { + q = pt_append_nulstring (parser, q, " AUTHID OWNER"); + } + else + { + q = pt_append_nulstring (parser, q, " AUTHID CALLER"); + } + } + r3 = pt_print_bytes (parser, p->info.sp.body); q = pt_append_varchar (parser, q, r3); - if (p->info.sp.comment != NULL) + if (p->info.sp.comment != NULL && !parser->flag.is_parsing_unload_schema) { r1 = pt_print_bytes (parser, p->info.sp.comment); q = pt_append_nulstring (parser, q, " comment "); @@ -7879,7 +7914,10 @@ pt_print_sp_parameter (PARSER_CONTEXT * parser, PT_NODE * p) r1 = pt_print_bytes (parser, p->info.sp_param.name); q = pt_append_varchar (parser, q, r1); q = pt_append_nulstring (parser, q, " "); - q = pt_append_nulstring (parser, q, pt_show_misc_type (p->info.sp_param.mode)); + q = pt_append_nulstring (parser, q, parser->flag.is_parsing_unload_schema ? + (p->info.sp_param.mode == PT_INPUT || p->info.sp_param.mode == PT_NOPUT) ? + "IN" : p->info.sp_param.mode == PT_OUTPUT ? + "OUT" : "INOUT" : pt_show_misc_type (p->info.sp_param.mode)); q = pt_append_nulstring (parser, q, " "); if (p->data_type) { @@ -7890,6 +7928,12 @@ pt_print_sp_parameter (PARSER_CONTEXT * parser, PT_NODE * p) q = pt_append_nulstring (parser, q, pt_show_type_enum (p->type_enum)); } + if (p->info.sp_param.default_value != NULL) + { + r1 = pt_print_bytes (parser, p->info.sp_param.default_value); + q = pt_append_varchar (parser, q, r1); + } + if (p->info.sp_param.comment != NULL) { r1 = pt_print_bytes (parser, p->info.sp_param.comment); @@ -7924,8 +7968,7 @@ static PARSER_VARCHAR * pt_print_sp_body (PARSER_CONTEXT * parser, PT_NODE * p) { PARSER_VARCHAR *q = NULL, *r1 = NULL; - - q = pt_append_nulstring (parser, q, " as "); + q = pt_append_nulstring (parser, q, parser->flag.is_parsing_unload_schema ? " AS\n" : " as "); if (p->info.sp_body.lang == SP_LANG_PLCSQL) { // TODO: PL/CSQL compiler should permit it. @@ -7963,8 +8006,13 @@ pt_print_sp_body (PARSER_CONTEXT * parser, PT_NODE * p) } */ } + q = pt_append_varchar (parser, q, r1); - q = pt_append_nulstring (parser, q, ";"); + + if (!parser->flag.is_parsing_unload_schema) + { + q = pt_append_nulstring (parser, q, ";"); + } return q; } @@ -8333,6 +8381,11 @@ pt_print_alter_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * p) q = pt_append_varchar (parser, q, r1); } + if (sp_info->recompile == 1) + { + q = pt_append_nulstring (parser, q, " recompile "); + } + if (sp_info->comment != NULL) { r1 = pt_print_bytes (parser, sp_info->comment); @@ -8553,11 +8606,34 @@ pt_print_datatype (PARSER_CONTEXT * parser, PT_NODE * p) } break; case PT_TYPE_NCHAR: + if (parser->flag.is_parsing_unload_schema) + { + q = pt_append_nulstring (parser, q, "national character"); + break; + } case PT_TYPE_VARNCHAR: + if (parser->flag.is_parsing_unload_schema) + { + q = pt_append_nulstring (parser, q, "national character varying"); + break; + } case PT_TYPE_CHAR: + if (parser->flag.is_parsing_unload_schema) + { + q = pt_append_nulstring (parser, q, "character"); + break; + } case PT_TYPE_VARCHAR: - show_collation = true; - /* FALLTHRU */ + if (!parser->flag.is_parsing_unload_schema) + { + show_collation = true; + /* FALLTHRU */ + } + else + { + q = pt_append_nulstring (parser, q, "character varying"); + break; + } case PT_TYPE_BIT: case PT_TYPE_VARBIT: case PT_TYPE_FLOAT: @@ -13336,7 +13412,10 @@ pt_print_isolation_lvl (PARSER_CONTEXT * parser, PT_NODE * p) static PT_NODE * pt_apply_method_call (PARSER_CONTEXT * parser, PT_NODE * p, void *arg) { - PT_APPLY_WALK (parser, p->info.method_call.method_name, arg); + if (PT_IS_METHOD (p)) + { + PT_APPLY_WALK (parser, p->info.method_call.method_name, arg); + } PT_APPLY_WALK (parser, p->info.method_call.arg_list, arg); PT_APPLY_WALK (parser, p->info.method_call.on_call_target, arg); PT_APPLY_WALK (parser, p->info.method_call.to_return_var, arg); @@ -18901,7 +18980,8 @@ pt_json_table_column_behavior_to_string (const json_table_column_behavior_type & // column_behavior (in) : column behavior // static PARSER_VARCHAR * -pt_print_json_table_column_error_or_empty_behavior (PARSER_CONTEXT * parser, PARSER_VARCHAR * pstr, +pt_print_json_table_column_error_or_empty_behavior (PARSER_CONTEXT * parser, + PARSER_VARCHAR * pstr, const struct json_table_column_behavior &column_behavior) { PARSER_VARCHAR *substr = NULL; diff --git a/src/parser/parser.h b/src/parser/parser.h index 62f68890ec8..446024d7bf3 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -178,7 +178,10 @@ extern "C" extern PT_NODE *pt_get_node_from_list (PT_NODE * list, int index); extern PT_NODE *pt_get_select_list (PARSER_CONTEXT * parser, PT_NODE * query); + + extern PT_NODE *pt_make_data_default_expr_node (PARSER_CONTEXT * parser, PT_NODE * expr); extern PT_OP_TYPE pt_op_type_from_default_expr_type (DB_DEFAULT_EXPR_TYPE expr_type); + extern int pt_associate_label_with_value_check_reference (const char *label, DB_VALUE * val); extern DB_VALUE *pt_find_value_of_label (const char *label); #if defined(ENABLE_UNUSED_FUNCTION) @@ -674,6 +677,8 @@ extern "C" int *continue_walk); extern void pt_get_default_expression_from_data_default_node (PARSER_CONTEXT * parser, PT_NODE * data_default_node, DB_DEFAULT_EXPR * default_expr); + extern void pt_get_default_expression_from_string (PARSER_CONTEXT * parser, const char *str, const int str_size, + DB_DEFAULT_EXPR * default_expr); extern PT_NODE *pt_has_name_oid (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk); extern int pt_check_dblink_password (PARSER_CONTEXT * parser, const char *passwd, char *cipher, int ciper_size); diff --git a/src/parser/parser_message.h b/src/parser/parser_message.h index efe01b11c33..db177a312c4 100644 --- a/src/parser/parser_message.h +++ b/src/parser/parser_message.h @@ -504,6 +504,14 @@ #define MSGCAT_SEMANTIC_SP_INTO_FIELD_EXPR_IN_NON_STATIC_SQL MSGCAT_SEMANTIC_NO(324) #define MSGCAT_SEMANTIC_NOT_SUPPORT_TYPE_TO_DATE_LANG MSGCAT_SEMANTIC_NO(325) +#define MSGCAT_SEMANTIC_NOT_SUPPORT_TYPE_TO_DATE_LANG MSGCAT_SEMANTIC_NO(325) +#define MSTCAT_SEMANTIC_SP_NOT_EXIST MSGCAT_SEMANTIC_NO(326) +#define MSGCAT_SEMANTIC_SP_OUT_DEFAULT_ARG_NOT_ALLOWED MSGCAT_SEMANTIC_NO(327) +#define MSGCAT_SEMANTIC_SP_NON_TRAILING_OPTIONAL_PARAMS MSGCAT_SEMANTIC_NO(328) +#define MSGCAT_SEMATNIC_AU_GRANT_OPTION_NOT_ALLOWED MSGCAT_SEMANTIC_NO(329) + + + /* Message id in the set MSGCAT_SET_PARSER_RUNTIME */ #define MSGCAT_RUNTIME_NO(n) n #define MSGCAT_RUNTIME_OUT_OF_MEMORY MSGCAT_RUNTIME_NO(1) diff --git a/src/parser/parser_support.c b/src/parser/parser_support.c index d0727f285df..eb6aaf6fb9d 100644 --- a/src/parser/parser_support.c +++ b/src/parser/parser_support.c @@ -1522,7 +1522,7 @@ pt_is_method_call (PT_NODE * node) } node = pt_get_end_path_node (node); - return (node->node_type == PT_METHOD_CALL); + return (PT_IS_METHOD (node)); } /* @@ -7769,33 +7769,26 @@ pt_make_query_show_grants_curr_usr (PARSER_CONTEXT * parser) return node; } +static PT_NODE * +pt_set_auth_bypass_mask_for_show (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk) +{ + DB_AUTH *auth_bypass; + + assert (arg != NULL); + + if (node && node->node_type == PT_SPEC) + { + auth_bypass = (DB_AUTH *) arg; + node->info.spec.auth_bypass_mask = *auth_bypass; + } + + return node; +} + /* * pt_make_query_show_grants() - builds the query used for SHOW GRANTS for a * given user * - * SELECT CONCAT ( 'GRANT ', - * GROUP_CONCAT(AU.auth_type ORDER BY 1 SEPARATOR ', '), - * ' ON ' , - * AU.class_of.class_name, - * ' TO ', - * AU.grantee.name , - * IF (AU.is_grantable=1, - * ' WITH GRANT OPTION', - * '') - * ) AS GRANTS - * FROM db_class C, _db_auth AU - * WHERE AU.class_of.unique_name = C.unique_name AND - * AU.class_of.owner.name = C.owner_name AND - * C.is_system_class='NO' AND - * ( AU.grantee.name= OR - * SET{ AU.grantee.name} SUBSETEQ ( - * SELECT SUM(SET{t.g.name}) - * FROM db_user U, TABLE(groups) AS t(g) - * WHERE U.name=) - * ) - * GROUP BY AU.grantee, AU.class_of, AU.is_grantable - * ORDER BY 1; - * * Note : The purpose of GROUP BY is to group all the privilege by user, * table and the presence of 'WITH GRANT OPTION' flag. We output the * privileges for the user but also for all groups to which the user @@ -7808,218 +7801,131 @@ pt_make_query_show_grants_curr_usr (PARSER_CONTEXT * parser) * parser(in): Parser context * user_name(in): DB user name */ + PT_NODE * pt_make_query_show_grants (PARSER_CONTEXT * parser, const char *original_user_name) { - PT_NODE *node = NULL; - PT_NODE *from_item = NULL; - PT_NODE *where_expr = NULL; - PT_NODE *concat_node = NULL; - PT_NODE *group_by_item = NULL; + PT_NODE **node = NULL; + PT_NODE *show_node = NULL; char user_name[SM_MAX_IDENTIFIER_LENGTH]; - assert (original_user_name != NULL); - assert (strlen (original_user_name) < SM_MAX_IDENTIFIER_LENGTH); + // *INDENT-OFF* + const static char *query = + "SELECT " + "CONCAT ('GRANT ', " + "GROUP_CONCAT([auth_type] ORDER BY 1 SEPARATOR ', '), " + "' ON '," + "IF ([object_type]=5, 'PROCEDURE ', ''), " + "[owner_name] || '.' || [object_name], " + "' TO '," + "[grantee_name]," + "IF ([is_grantable]=1, ' WITH GRANT OPTION', '')" + ") AS GRANTS " + "FROM (" + "SELECT " + "CAST ([a].[grantor].[name] AS VARCHAR(255)) AS [grantor_name], " /* string -> varchar(255) */ + "CAST ([a].[grantee].[name] AS VARCHAR(255)) AS [grantee_name], " /* string -> varchar(255) */ + "[a].[object_type] AS [object_type], " + "[c].[class_name] AS [object_name], " + "CAST ([c].[owner].[name] AS VARCHAR(255)) AS [owner_name], " /* string -> varchar(255) */ + "[a].[auth_type] AS [auth_type], " + "[a].[is_grantable] AS [is_grantable] " + "FROM " + "[_db_auth] AS [a], [_db_class] AS [c] " + "WHERE " + "[a].[object_of] = [c].[class_of] " + "AND [a].[object_type] = 0 " + "AND MOD ([c].[is_system_class], 2) = 0 " + "AND ( " + "[a].[grantee].[name] = '%1$s' " + "OR " + "SET {[a].[grantee].[name]} SUBSETEQ (" + "SELECT " + "SUM (SET {[t].[g].[name]}) " + "FROM " + /* AU_USER_CLASS_NAME */ + "[db_user] AS [u], TABLE ([u].[groups]) AS [t] ([g]) " + "WHERE " + "[u].[name] = '%1$s'" + ") " + ") " + "UNION ALL " + "SELECT " + "CAST ([a].[grantor].[name] AS VARCHAR(255)) AS [grantor_name], " /* string -> varchar(255) */ + "CAST ([a].[grantee].[name] AS VARCHAR(255)) AS [grantee_name], " /* string -> varchar(255) */ + "[a].[object_type] AS [object_type], " + "[s].[sp_name] AS [object_name], " + "CAST ([s].[owner].[name] AS VARCHAR(255)) AS [owner_name], " /* string -> varchar(255) */ + "[a].[auth_type] AS [auth_type], " + "[a].[is_grantable] AS [is_grantable] " + "FROM " + "[_db_auth] AS [a], [_db_stored_procedure] AS [s] " + "WHERE " + "[a].[object_of] = [s] " + "AND [a].[object_type] = 5 " + "AND [s].[is_system_generated] = 0 " + "AND ( " + "[a].[grantee].[name] = '%1$s' " + "OR " + "SET {[a].[grantee].[name]} SUBSETEQ (" + "SELECT " + "SUM (SET {[t].[g].[name]}) " + "FROM " + /* AU_USER_CLASS_NAME */ + "[db_user] AS [u], TABLE ([u].[groups]) AS [t] ([g]) " + "WHERE " + "[u].[name] = '%1$s'" + ") " + ") " + ") " + "GROUP BY " + "[grantee_name], [owner_name], [object_name], [is_grantable] ASC " + "ORDER BY 1;"; + // *INDENT-ON* + + const int buffer_size = 4096; // length of query (1303) + identifier (255) * 4 < 1024 + char buffer[buffer_size]; + memset (buffer, 0, buffer_size); /* conversion to uppercase can cause to double size, if internationalization is used : size * accordingly */ intl_identifier_upper (original_user_name, user_name); - node = parser_new_node (parser, PT_SELECT); - if (node == NULL) - { - return NULL; - } - - PT_SELECT_INFO_SET_FLAG (node, PT_SELECT_INFO_READ_ONLY); - - /* ------ SELECT list ------- */ - /* - * CONCAT ( 'GRANT ', - * GROUP_CONCAT(AU.auth_type ORDER BY 1 SEPARATOR ', '), - * ' ON ' , - * AU.class_of.unique_name, - * ' TO ', - * AU.grantee.name , - * IF (AU.is_grantable=1, - * ' WITH GRANT OPTION', - * '') - * ) AS GRANTS - */ - { - PT_NODE *concat_arg_list = NULL; - PT_NODE *concat_arg = NULL; + snprintf (buffer, buffer_size, query, user_name); - concat_arg = pt_make_string_value (parser, "GRANT "); - concat_arg_list = parser_append_node (concat_arg, concat_arg_list); + /* parser ';' will empty and reset the stack of parser, this make the status machine be right for the next statement, + * and avoid nested parser statement. */ + parser_parse_string (parser, ";"); + node = parser_parse_string_use_sys_charset (parser, buffer); + if (node == NULL) { - /* GROUP_CONCAT(AU.auth_type ORDER BY 1 SEPARATOR ', ') */ - PT_NODE *group_concat_field = NULL; - PT_NODE *group_concat_sep = NULL; - PT_NODE *order_by_item = NULL; - - concat_arg = parser_new_node (parser, PT_FUNCTION); - if (concat_arg == NULL) - { - return NULL; - } - - concat_arg->info.function.function_type = PT_GROUP_CONCAT; - concat_arg->info.function.all_or_distinct = PT_ALL; - - group_concat_field = pt_make_dotted_identifier (parser, "AU.auth_type"); - group_concat_sep = pt_make_string_value (parser, ", "); - concat_arg->info.function.arg_list = parser_append_node (group_concat_sep, group_concat_field); - - /* add ORDER BY */ - assert (concat_arg->info.function.order_by == NULL); - - /* By 1 */ - order_by_item = pt_make_sort_spec_with_number (parser, 1, PT_ASC); - concat_arg->info.function.order_by = order_by_item; + return NULL; } - concat_arg_list = parser_append_node (concat_arg, concat_arg_list); - concat_arg = pt_make_string_value (parser, " ON "); - concat_arg_list = parser_append_node (concat_arg, concat_arg_list); - - concat_arg = pt_make_dotted_identifier (parser, "AU.class_of.unique_name"); - concat_arg_list = parser_append_node (concat_arg, concat_arg_list); - - concat_arg = pt_make_string_value (parser, " TO "); - concat_arg_list = parser_append_node (concat_arg, concat_arg_list); + parser->flag.dont_collect_exec_stats = 1; - concat_arg = pt_make_dotted_identifier (parser, "AU.grantee.name"); - concat_arg_list = parser_append_node (concat_arg, concat_arg_list); + show_node = pt_pop (parser); + assert (show_node == node[0]); - /* IF (AU.is_grantable=1, ' WITH GRANT OPTION','') */ + if (show_node) { - PT_NODE *pred_for_if = NULL; - - pred_for_if = pt_make_pred_name_int_val (parser, PT_EQ, "AU.is_grantable", 1); - concat_arg = pt_make_if_with_strings (parser, pred_for_if, " WITH GRANT OPTION", "", NULL); - } - concat_arg_list = parser_append_node (concat_arg, concat_arg_list); - - concat_node = parser_keyword_func ("concat", concat_arg_list); - if (concat_node == NULL) - { - return NULL; - } + DB_AUTH bypass_auth = DB_AUTH_SELECT; + show_node = parser_walk_tree (parser, show_node, pt_set_auth_bypass_mask_for_show, &bypass_auth, NULL, NULL); - { + // for backward compatibiltiy char col_alias[SM_MAX_IDENTIFIER_LENGTH] = { 0 }; const char *const col_header = "Grants for "; strcpy (col_alias, col_header); strncat (col_alias, user_name, SM_MAX_IDENTIFIER_LENGTH - strlen (col_header) - 1); col_alias[SM_MAX_IDENTIFIER_LENGTH - 1] = '\0'; - concat_node->alias_print = pt_append_string (parser, NULL, col_alias); - } - } - node->info.query.q.select.list = parser_append_node (concat_node, node->info.query.q.select.list); - - /* ------ SELECT ... FROM ------- */ - from_item = pt_add_table_name_to_from_list (parser, node, "db_class", "C", DB_AUTH_SELECT); - - from_item = pt_add_table_name_to_from_list (parser, node, "_db_auth", "AU", DB_AUTH_SELECT); - - /* ------ SELECT ... WHERE ------- */ - /* - * WHERE AU.class_of.class_name = C.class_name AND - * AU.class_of.owner.name = C.owner_name AND - * C.is_system_class='NO' AND - * ( AU.grantee.name= OR - * SET{ AU.grantee.name} SUBSETEQ ( ) - * ) - */ - { - /* AU.class_of.class_name = C.class_name */ - PT_NODE *where_item = NULL; - - where_item = pt_make_pred_with_identifiers (parser, PT_EQ, "AU.class_of.class_name", "C.class_name"); - where_expr = where_item; - } - { - /* AU.class_of.owner.name = C.owner_name */ - PT_NODE *where_item = NULL; - where_item = pt_make_pred_with_identifiers (parser, PT_EQ, "AU.class_of.owner.name", "C.owner_name"); - /* = AND */ - where_expr = parser_make_expression (parser, PT_AND, where_expr, where_item, NULL); - } - { - /* C.is_system_class = 'NO' */ - PT_NODE *where_item = NULL; - - where_item = pt_make_pred_name_string_val (parser, PT_EQ, "C.is_system_class", "NO"); - /* = AND */ - where_expr = parser_make_expression (parser, PT_AND, where_expr, where_item, NULL); - } - { - PT_NODE *user_cond = NULL; - PT_NODE *group_cond = NULL; - /* AU.grantee.name = */ - user_cond = pt_make_pred_name_string_val (parser, PT_EQ, "AU.grantee.name", user_name); - - /* SET{ AU.grantee.name} SUBSETEQ ( */ - { - /* query to get a SET of user's groups */ - PT_NODE *query_user_groups = NULL; - PT_NODE *set_of_grantee_name = NULL; - - { - /* SET{ AU.grantee.name} */ - PT_NODE *grantee_name_identifier = NULL; - - grantee_name_identifier = pt_make_dotted_identifier (parser, "AU.grantee.name"); - set_of_grantee_name = parser_new_node (parser, PT_VALUE); - if (set_of_grantee_name == NULL) - { - return NULL; - } - set_of_grantee_name->info.value.data_value.set = grantee_name_identifier; - set_of_grantee_name->type_enum = PT_TYPE_SET; - } - - query_user_groups = pt_make_query_user_groups (parser, user_name); - - group_cond = parser_make_expression (parser, PT_SUBSETEQ, set_of_grantee_name, query_user_groups, NULL); + PT_NODE *concat_node = show_node->info.query.q.select.list; + concat_node->alias_print = pt_append_string (parser, NULL, col_alias); } - user_cond = parser_make_expression (parser, PT_OR, user_cond, group_cond, NULL); - - where_expr = parser_make_expression (parser, PT_AND, where_expr, user_cond, NULL); - } - - - - /* WHERE list should be empty */ - assert (node->info.query.q.select.where == NULL); - node->info.query.q.select.where = parser_append_node (where_expr, node->info.query.q.select.where); - - /* GROUP BY : AU.grantee, AU.class_of, AU.is_grantable */ - assert (node->info.query.q.select.group_by == NULL); - group_by_item = pt_make_sort_spec_with_identifier (parser, "AU.grantee", PT_ASC); - node->info.query.q.select.group_by = parser_append_node (group_by_item, node->info.query.q.select.group_by); - - group_by_item = pt_make_sort_spec_with_identifier (parser, "AU.class_of", PT_ASC); - node->info.query.q.select.group_by = parser_append_node (group_by_item, node->info.query.q.select.group_by); - - group_by_item = pt_make_sort_spec_with_identifier (parser, "AU.is_grantable", PT_ASC); - node->info.query.q.select.group_by = parser_append_node (group_by_item, node->info.query.q.select.group_by); - group_by_item = NULL; - - { - PT_NODE *order_by_item = NULL; - assert (node->info.query.order_by == NULL); - - /* By GROUPS */ - order_by_item = pt_make_sort_spec_with_number (parser, 1, PT_ASC); - node->info.query.order_by = parser_append_node (order_by_item, node->info.query.order_by); - } - return node; + return show_node; } /* @@ -10397,6 +10303,144 @@ pt_has_non_groupby_column_node (PARSER_CONTEXT * parser, PT_NODE * node, void *a return node; } +static DB_DEFAULT_EXPR_TYPE +parse_default_expr_type (const char *str, const int str_size, int *next_len) +{ + if (str_size < 4) + { + *next_len = 0; + return DB_DEFAULT_NONE; + } + + switch (str[0]) + { + case 'S': + if (str_size >= 8) + { + if (strncmp (str, "SYS_DATE", 8) == 0) + { + *next_len = 8; + return DB_DEFAULT_SYSDATE; + } + if (strncmp (str, "SYS_TIME", 8) == 0) + { + *next_len = 8; + return DB_DEFAULT_SYSTIME; + } + } + if (str_size >= 12 && strncmp (str, "SYS_DATETIME", 12) == 0) + { + *next_len = 12; + return DB_DEFAULT_SYSDATETIME; + } + if (str_size >= 13 && strncmp (str, "SYS_TIMESTAMP", 13) == 0) + { + *next_len = 13; + return DB_DEFAULT_SYSTIMESTAMP; + } + break; + + case 'C': + if (str_size >= 12) + { + if (strncmp (str, "CURRENT_DATE", 12) == 0) + { + *next_len = 12; + return DB_DEFAULT_CURRENTDATE; + } + if (strncmp (str, "CURRENT_TIME", 12) == 0) + { + *next_len = 12; + return DB_DEFAULT_CURRENTTIME; + } + if (strncmp (str, "CURRENT_USER", 12) == 0) + { + *next_len = 12; + return DB_DEFAULT_CURR_USER; + } + } + if (str_size >= 16 && strncmp (str, "CURRENT_DATETIME", 16) == 0) + { + *next_len = 16; + return DB_DEFAULT_CURRENTDATETIME; + } + if (str_size >= 17 && strncmp (str, "CURRENT_TIMESTAMP", 17) == 0) + { + *next_len = 17; + return DB_DEFAULT_CURRENTTIMESTAMP; + } + break; + + case 'U': + if (str_size >= 16 && strncmp (str, "UNIX_TIMESTAMP()", 16) == 0) + { + *next_len = 16; + return DB_DEFAULT_UNIX_TIMESTAMP; + } + if (str_size >= 6 && strncmp (str, "USER()", 6) == 0) + { + *next_len = 6; + return DB_DEFAULT_USER; + } + if (str_size >= 4 && strncmp (str, "USER", 4) == 0) + { + *next_len = 4; + return DB_DEFAULT_CURR_USER; + } + break; + } + + *next_len = 0; + return DB_DEFAULT_NONE; +} + +/* + * pt_get_default_expression_from_string () - get default value from string + * return : error code or NO_ERROR + * + * parser (in) : parser context + * str (in) : default expression string + * str_size (in) : default expression string size + * default_expr (out) : default expression + */ +void +pt_get_default_expression_from_string (PARSER_CONTEXT * parser, const char *str, const int str_size, + DB_DEFAULT_EXPR * default_expr) +{ + assert (parser != NULL && default_expr != NULL); + assert (str != NULL && str_size > 0); + + classobj_initialize_default_expr (default_expr); + + std::string expr_str (str, str_size); + + int curr_idx = 0; + int curr_len = str_size; + + const int to_char_size = sizeof ("TO_CHAR(") - 1; + if (str_size > to_char_size && strncmp (str, "TO_CHAR(", to_char_size) == 0) + { + curr_idx += to_char_size; + curr_len -= to_char_size; + default_expr->default_expr_op = T_TO_CHAR; + } + + int parsed_len; + default_expr->default_expr_type = parse_default_expr_type (&str[curr_idx], curr_len, &parsed_len); + curr_idx += parsed_len; + curr_len -= parsed_len; + + if (default_expr->default_expr_op == T_TO_CHAR) + { + // find next ',' + const char *formatted_string = strchr (&str[curr_idx], ',') + 1; + + // get remaining length before the last ')' + int remaining_len = str_size - (formatted_string - &str[curr_idx]); + default_expr->default_expr_format = strndup (formatted_string, remaining_len - 1); + } +} + /* * pt_get_default_value_from_attrnode () - get default value from data default node * return : error code or NO_ERROR @@ -10501,7 +10545,7 @@ pt_set_user_specified_name (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, switch (node->node_type) { case PT_NAME: - if (PT_NAME_INFO_IS_FLAGED (node, PT_NAME_INFO_USER_SPECIFIED)) + if (PT_NAME_INFO_IS_FLAGED (node, PT_NAME_INFO_USER_SPECIFIED) || node->info.name.meta_class == PT_META_CLASS) { original_name = node->info.name.original; resolved_name = node->info.name.resolved; @@ -10680,7 +10724,7 @@ pt_set_user_specified_name (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, } // *INDENT-OFF* - assert ((node->node_type == PT_NAME && PT_NAME_INFO_IS_FLAGED (node, PT_NAME_INFO_USER_SPECIFIED)) + assert ((node->node_type == PT_NAME && (PT_NAME_INFO_IS_FLAGED (node, PT_NAME_INFO_USER_SPECIFIED) || node->info.name.meta_class == PT_META_CLASS)) || (node->node_type == PT_EXPR && PT_IS_SERIAL (node->info.expr.op))); // *INDENT-ON* assert (original_name && original_name[0] != '\0'); @@ -10695,7 +10739,7 @@ pt_set_user_specified_name (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, { PT_ERRORf2 (parser, node, "Object name [%s] not allowed. It cannot exceed %d bytes.", - pt_short_print (parser, node), DB_MAX_IDENTIFIER_LENGTH - DB_MAX_USER_LENGTH); + pt_short_print (parser, node), (DB_MAX_IDENTIFIER_LENGTH - DB_MAX_USER_LENGTH) - 1); *continue_walk = PT_STOP_WALK; return node; } @@ -12062,3 +12106,87 @@ pt_rewrite_for_dblink (PARSER_CONTEXT * parser, PT_NODE * stmt) return; } + +extern PT_NODE * +pt_make_data_default_expr_node (PARSER_CONTEXT * parser, PT_NODE * expr) +{ + PT_NODE *node = parser_new_node (parser, PT_DATA_DEFAULT); + if (node) + { + PT_NODE *def; + node->info.data_default.default_value = expr; + node->info.data_default.shared = PT_DEFAULT; + + def = node->info.data_default.default_value; + if (def && def->node_type == PT_EXPR) + { + if (def->info.expr.op == PT_TO_CHAR) + { + if (def->info.expr.arg3) + { + bool has_user_lang = false; + bool dummy; + + assert (def->info.expr.arg3->node_type == PT_VALUE); + (void) lang_get_lang_id_from_flag (def->info.expr.arg3->info.value.data_value.i, &dummy, + &has_user_lang); + if (has_user_lang) + { + PT_ERROR (parser, def->info.expr.arg3, "do not allow lang format in default to_char"); + } + } + + if (def->info.expr.arg1 && def->info.expr.arg1->node_type == PT_EXPR) + { + def = def->info.expr.arg1; + } + } + + switch (def->info.expr.op) + { + case PT_SYS_TIME: + node->info.data_default.default_expr_type = DB_DEFAULT_SYSTIME; + break; + case PT_SYS_DATE: + node->info.data_default.default_expr_type = DB_DEFAULT_SYSDATE; + break; + case PT_SYS_DATETIME: + node->info.data_default.default_expr_type = DB_DEFAULT_SYSDATETIME; + break; + case PT_SYS_TIMESTAMP: + node->info.data_default.default_expr_type = DB_DEFAULT_SYSTIMESTAMP; + break; + case PT_CURRENT_TIME: + node->info.data_default.default_expr_type = DB_DEFAULT_CURRENTTIME; + break; + case PT_CURRENT_DATE: + node->info.data_default.default_expr_type = DB_DEFAULT_CURRENTDATE; + break; + case PT_CURRENT_DATETIME: + node->info.data_default.default_expr_type = DB_DEFAULT_CURRENTDATETIME; + break; + case PT_CURRENT_TIMESTAMP: + node->info.data_default.default_expr_type = DB_DEFAULT_CURRENTTIMESTAMP; + break; + case PT_USER: + node->info.data_default.default_expr_type = DB_DEFAULT_USER; + break; + case PT_CURRENT_USER: + node->info.data_default.default_expr_type = DB_DEFAULT_CURR_USER; + break; + case PT_UNIX_TIMESTAMP: + node->info.data_default.default_expr_type = DB_DEFAULT_UNIX_TIMESTAMP; + break; + default: + node->info.data_default.default_expr_type = DB_DEFAULT_NONE; + break; + } + } + else + { + node->info.data_default.default_expr_type = DB_DEFAULT_NONE; + } + } + + return node; +} diff --git a/src/parser/semantic_check.c b/src/parser/semantic_check.c index 06fc33ae844..520a7e8c68e 100644 --- a/src/parser/semantic_check.c +++ b/src/parser/semantic_check.c @@ -46,6 +46,7 @@ #include "db_json.hpp" #include "object_primitive.h" #include "db_client_type.hpp" +#include "msgcat_glossary.hpp" #include "dbtype.h" #define PT_CHAIN_LENGTH 10 @@ -273,6 +274,7 @@ static PT_NODE *pt_check_where (PARSER_CONTEXT * parser, PT_NODE * node); static int pt_check_range_partition_strict_increasing (PARSER_CONTEXT * parser, PT_NODE * stmt, PT_NODE * part, PT_NODE * part_next, PT_NODE * column_dt); static int pt_coerce_partition_value_with_data_type (PARSER_CONTEXT * parser, PT_NODE * value, PT_NODE * data_type); +static int pt_check_default_value_param_for_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * param); /* pt_combine_compatible_info () - combine two cinfo into cinfo1 * return: true if compatible, else false @@ -9504,6 +9506,67 @@ pt_get_type_name (PT_TYPE_ENUM type_enum, PT_NODE * data_type) return pt_show_type_enum (type_enum); } +/* + * pt_check_default_value_param_for_stored_procedure () - do semantic checks for default value params' invalid form: Out parameter, system expressions, incoercible type + * return: none + * parser(in): the parser context used to derive the statement + * node(in): a statement + */ +static int +pt_check_default_value_param_for_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * param) +{ + int error = NO_ERROR; + PT_NODE *node_ptr = NULL; + PT_NODE *default_value_node = NULL; + PT_NODE *default_value = NULL; + const char *default_value_print = NULL; + + default_value_node = param->info.sp_param.default_value = + pt_check_data_default (parser, param->info.sp_param.default_value); + if (pt_has_error (parser)) + { + return error; + } + + assert (default_value_node != NULL && default_value_node->info.data_default.shared == PT_DEFAULT); + + default_value = default_value_node->info.data_default.default_value; + default_value_print = pt_short_print (parser, default_value); + + if (param->info.sp_param.mode != PT_INPUT && param->info.sp_param.mode != PT_NOPUT) + { + PT_ERRORmf (parser, + param, + MSGCAT_SET_PARSER_SEMANTIC, + MSGCAT_SEMANTIC_SP_OUT_DEFAULT_ARG_NOT_ALLOWED, pt_short_print (parser, param->info.sp_param.name)); + return error; + } + + if (default_value_node->info.data_default.default_expr_type != DB_DEFAULT_NONE) + { + PT_ERRORmf (parser, + default_value_node->info.data_default.default_value, + MSGCAT_SET_PARSER_SEMANTIC, + MSGCAT_SEMANTIC_DEFAULT_EXPR_NOT_ALLOWED, + pt_short_print (parser, default_value_node->info.data_default.default_value)); + } + else + { + error = + pt_coerce_value_for_default_value (parser, default_value, default_value, param->type_enum, + param->data_type, default_value_node->info.data_default.default_expr_type); + if (error != NO_ERROR) + { + error = + (error == ER_IT_DATA_OVERFLOW) ? MSGCAT_SEMANTIC_OVERFLOW_COERCING_TO : MSGCAT_SEMANTIC_CANT_COERCE_TO; + PT_ERRORmf2 (parser, default_value, MSGCAT_SET_PARSER_SEMANTIC, error, + default_value_print, pt_get_type_name (param->type_enum, param->data_type)); + } + } + + return error; +} + /* * pt_check_create_stored_procedure () - do semantic checks on the create procedure/function statement * return: none @@ -9513,10 +9576,39 @@ pt_get_type_name (PT_TYPE_ENUM type_enum, PT_NODE * data_type) static void pt_check_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * node) { - PT_NODE *param; - + int error = NO_ERROR; + PT_NODE *param = NULL; + PT_NODE *default_value_node = NULL; + PT_NODE *default_value = NULL; + PT_NODE *initial_def_val = NULL; + int param_count = 0; + bool has_default_value = false; bool is_plcsql = (node->info.sp.body->info.sp_body.lang == SP_LANG_PLCSQL); + DB_OBJECT *owner = NULL; + PT_NODE *name = node->info.sp.name; + const char *owner_name = pt_get_qualifier_name (parser, name); + if (owner_name) + { + owner = db_find_user (owner_name); + if (owner == NULL) + { + ASSERT_ERROR_AND_SET (error); + + if (er_errid () == ER_AU_INVALID_USER) + { + PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_USER_IS_NOT_IN_DB, owner_name); + } + return; + } + else if (au_is_dba_group_member (Au_user) == false && ws_is_same_object (owner, Au_user) == false) + { + PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_SYNONYM_NOT_OWNER, + "CREATE PROCEDURE/FUNCTION"); + return; + } + } + for (param = node->info.sp.param_list; param; param = param->next) { if (param->type_enum == PT_TYPE_NONE) @@ -9543,7 +9635,32 @@ pt_check_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * node) PT_ERRORmf (parser, param, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_NOT_SUPPORTED_SP_ARG_TYPE, pt_get_type_name (param->type_enum, param->data_type)); } - return; + goto end; + } + + /* check trailing arguments */ + if (param->info.sp_param.default_value != NULL) + { + has_default_value = true; + // check default value + error = pt_check_default_value_param_for_stored_procedure (parser, param); + if (error != NO_ERROR) + { + goto end; + } + } + else + { + // error for non-trailing arguments + if (has_default_value) + { + PT_ERRORmf (parser, + param, + MSGCAT_SET_PARSER_SEMANTIC, + MSGCAT_SEMANTIC_SP_NON_TRAILING_OPTIONAL_PARAMS, + pt_short_print (parser, param->info.sp_param.name)); + goto end; + } } } @@ -9575,9 +9692,12 @@ pt_check_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * node) MSGCAT_SEMANTIC_NOT_SUPPORTED_SP_RET_TYPE, pt_get_type_name (node->info.sp.ret_type, node->info.sp.ret_data_type)); } - return; + goto end; } } + +end: + return; } /* @@ -9850,10 +9970,48 @@ pt_check_grant_revoke (PARSER_CONTEXT * parser, PT_NODE * node) const char *username; PT_FLAT_SPEC_INFO info; - /* Replace each Entity Spec with an Equivalent flat list */ - info.spec_parent = NULL; - info.for_update = false; - parser_walk_tree (parser, node, pt_flat_spec_pre, &info, pt_continue_walk, NULL); + bool is_for_spec = true; + PT_NODE *auth_cmd_list = node->info.grant.auth_cmd_list; + while (auth_cmd_list) + { + PT_PRIV_TYPE pt_auth = auth_cmd_list->info.auth_cmd.auth_cmd; + if (pt_auth == PT_EXECUTE_PROCEDURE_PRIV) + { + is_for_spec = false; + break; + } + + auth_cmd_list = auth_cmd_list->next; + } + + if (is_for_spec == true) + { + /* Replace each Entity Spec with an Equivalent flat list */ + info.spec_parent = NULL; + info.for_update = false; + parser_walk_tree (parser, node, pt_flat_spec_pre, &info, pt_continue_walk, NULL); + } + else + { + /* check grant option */ + if (node->info.grant.grant_option == PT_GRANT_OPTION) + { + PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMATNIC_AU_GRANT_OPTION_NOT_ALLOWED, + MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_PROCEDURE)); + } + + /* check spec_list (procedures/functions) exists */ + for (PT_NODE * procs = node->info.grant.spec_list; procs != NULL; procs = procs->next) + { + // [TODO] Resovle user schema name, built-in package name + const char *proc_name = procs->info.name.original; + if (jsp_is_exist_stored_procedure (proc_name) == false) + { + PT_ERRORmf (parser, procs, MSGCAT_SET_PARSER_SEMANTIC, MSTCAT_SEMANTIC_SP_NOT_EXIST, proc_name); + break; + } + } + } /* make sure the grantees/revokees exist */ for ((user = (node->node_type == PT_GRANT ? node->info.grant.user_list : node->info.revoke.user_list)); user; @@ -14485,6 +14643,15 @@ pt_coerce_insert_values (PARSER_CONTEXT * parser, PT_NODE * stmt) /* test assignment compatibility. This sets parser->error_msgs */ PT_NODE *new_node; + if (parser->flag.is_parsing_static_sql == 1 && a->node_type != PT_NAME) + { + assert (a->node_type == PT_HOST_VAR); + PT_ERRORmf2 (parser, stmt, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CLASS_HAS_NO_ATTR, + pt_short_print (parser, stmt->info.insert.spec->info.spec.entity_name), + a->info.host_var.label); + continue; + } + new_node = pt_assignment_compatible (parser, a, v); if (new_node == NULL) { diff --git a/src/parser/type_checking.c b/src/parser/type_checking.c index 69f0b9d24a9..1da32ca7fb1 100644 --- a/src/parser/type_checking.c +++ b/src/parser/type_checking.c @@ -529,12 +529,11 @@ pt_get_expression_definition (const PT_OP_TYPE op, EXPRESSION_DEFINITION * def) num = 0; /* two overloads */ - /* arg1 */ sig.arg1_type.type = pt_arg_type::GENERIC; sig.arg1_type.val.generic_type = PT_GENERIC_TYPE_STRING; - /* return type */ + /* return type */ sig.return_type.type = pt_arg_type::NORMAL; sig.return_type.val.type = PT_TYPE_INTEGER; def->overloads[num++] = sig; @@ -542,10 +541,13 @@ pt_get_expression_definition (const PT_OP_TYPE op, EXPRESSION_DEFINITION * def) /* arg1 */ sig.arg1_type.type = pt_arg_type::GENERIC; sig.arg1_type.val.generic_type = PT_GENERIC_TYPE_BIT; + /* return type */ + def->overloads[num++] = sig; + /* arg1 */ + sig.arg1_type.type = pt_arg_type::NORMAL; + sig.arg1_type.val.type = PT_TYPE_BLOB; /* return type */ - sig.return_type.type = pt_arg_type::NORMAL; - sig.return_type.val.type = PT_TYPE_INTEGER; def->overloads[num++] = sig; def->overloads_count = num; @@ -6128,8 +6130,8 @@ pt_apply_expressions_definition (PARSER_CONTEXT * parser, PT_NODE ** node) return NO_ERROR; } - matches = -1; best_match = 0; + matches = -1; for (i = 0; i < def.overloads_count; i++) { int match_cnt = 0; @@ -9189,21 +9191,37 @@ pt_eval_expr_type (PARSER_CONTEXT * parser, PT_NODE * node) bool has_user_lang = false; const char *lang_str; - assert (arg3 != NULL && - (arg3->node_type == PT_HOST_VAR || (arg3->node_type == PT_VALUE && arg3_type == PT_TYPE_INTEGER))); + assert (arg3 != NULL); + assert ((arg3->node_type == PT_HOST_VAR) || + (arg3->node_type == PT_VALUE && arg3_type == PT_TYPE_INTEGER) || + (parser->flag.is_parsing_static_sql && arg3->node_type == PT_EXPR && arg3->info.expr.op == PT_CAST)); if (arg3->node_type != PT_HOST_VAR) { - /* change locale from date_lang (set by grammar) to number_lang */ - (void) lang_get_lang_id_from_flag (arg3->info.value.data_value.i, &has_user_format, &has_user_lang); - if (!has_user_lang) + if (arg3_type != PT_TYPE_INTEGER) + { + assert (parser->flag.is_parsing_static_sql && + arg3->node_type == PT_EXPR && arg3->info.expr.op == PT_CAST); + /* This part is not supported normally. + * This is a problem that has persisted since the previous version. + * I assume that you can enter here only when it is written as static sql in PLCSQL. + * Also, in this case, it is promised that actual execution will not be performed separately. + * For this reason, we skip over the actual lang_id, etc. without obtaining them. + */ + } + else { - int lang_flag; - lang_str = prm_get_string_value (PRM_ID_INTL_NUMBER_LANG); - (void) lang_set_flag_from_lang (lang_str, has_user_format, has_user_lang, &lang_flag); - arg3->info.value.data_value.i = lang_flag; - arg3->info.value.db_value_is_initialized = 0; - pt_value_to_db (parser, arg3); + /* change locale from date_lang (set by grammar) to number_lang */ + (void) lang_get_lang_id_from_flag (arg3->info.value.data_value.i, &has_user_format, &has_user_lang); + if (!has_user_lang) + { + int lang_flag; + lang_str = prm_get_string_value (PRM_ID_INTL_NUMBER_LANG); + (void) lang_set_flag_from_lang (lang_str, has_user_format, has_user_lang, &lang_flag); + arg3->info.value.data_value.i = lang_flag; + arg3->info.value.db_value_is_initialized = 0; + pt_value_to_db (parser, arg3); + } } } } @@ -15759,6 +15777,24 @@ pt_evaluate_db_value_expr (PARSER_CONTEXT * parser, PT_NODE * expr, PT_OP_TYPE o if (!PT_IS_STRING_TYPE (o1->type_enum)) { + if (o1->type_enum == PT_TYPE_BLOB) + { + DB_VALUE tval; + + db_make_null (&tval); + dom_status = tp_value_cast (arg1, &tval, &tp_VarBit_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + PT_ERRORmf2 (parser, o1, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CANT_COERCE_TO, + pt_short_print (parser, o1), pt_show_type_enum (rTyp)); + db_value_clear (&tval); + return 0; + } + db_make_int (result, db_get_string_size (&tval)); + db_value_clear (&tval); + return 1; + } + return 0; } @@ -15774,6 +15810,27 @@ pt_evaluate_db_value_expr (PARSER_CONTEXT * parser, PT_NODE * expr, PT_OP_TYPE o if (!PT_IS_STRING_TYPE (o1->type_enum)) { + if (o1->type_enum == PT_TYPE_BLOB) + { + DB_VALUE tval; + int len = 0; + + db_make_null (&tval); + dom_status = tp_value_cast (arg1, &tval, &tp_VarBit_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + PT_ERRORmf2 (parser, o1, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CANT_COERCE_TO, + pt_short_print (parser, o1), pt_show_type_enum (rTyp)); + db_value_clear (&tval); + return 0; + } + + db_get_bit (&tval, &len); + db_make_int (result, len); + db_value_clear (&tval); + return 1; + } + return 0; } @@ -19203,6 +19260,11 @@ pt_semantic_type (PARSER_CONTEXT * parser, PT_NODE * tree, SEMANTIC_CHK_INFO * s } /* do type checking */ tree = parser_walk_tree (parser, tree, pt_eval_type_pre, sc_info_ptr, pt_eval_type, sc_info_ptr); + if (pt_has_error (parser)) + { + tree = NULL; + return tree; + } /* do constant folding */ tree = parser_walk_tree (parser, tree, pt_fold_constants_pre, NULL, pt_fold_constants_post, sc_info_ptr); if (pt_has_error (parser)) @@ -20377,6 +20439,8 @@ pt_is_op_hv_late_bind (PT_OP_TYPE op) case PT_HOURF: case PT_MINUTEF: case PT_SECONDF: + case PT_BIT_LENGTH: + case PT_OCTET_LENGTH: case PT_TO_DATE: case PT_TO_DATETIME: case PT_TO_DATETIME_TZ: diff --git a/src/parser/view_transform.c b/src/parser/view_transform.c index bcf1d2882d2..80eb3575ed3 100644 --- a/src/parser/view_transform.c +++ b/src/parser/view_transform.c @@ -1632,7 +1632,7 @@ mq_substitute_spec_in_method_and_hints (PARSER_CONTEXT * parser, PT_NODE * node, switch (node->node_type) { case PT_METHOD_CALL: - if ((node->info.method_call.method_name) + if (PT_IS_METHOD (node) && (node->info.method_call.method_name) && (node->info.method_call.method_name->info.name.spec_id == info->old_id)) { node->info.method_call.method_name->info.name.spec_id = info->new_id; @@ -3222,6 +3222,11 @@ mq_translate_tree (PARSER_CONTEXT * parser, PT_NODE * tree, PT_NODE * spec_list, return NULL; } + if (PT_IS_FOR_PL_COMPILE (parser) && sm_is_system_vclass (entity->info.name.original)) + { + continue; + } + if (!fetch_for_update) { subquery = mq_fetch_subqueries (parser, entity); @@ -3394,13 +3399,10 @@ mq_class_meth_corr_subq_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *void *continue_walk = PT_CONTINUE_WALK; - if (node->node_type == PT_METHOD_CALL) + if (PT_IS_CLASS_METHOD (node)) { /* found class method */ - if (node->info.method_call.method_type == PT_IS_CLASS_MTHD) - { - *found = true; - } + *found = true; } else if (pt_is_query (node)) { @@ -8364,7 +8366,7 @@ mq_reset_spec_ids (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int static PT_NODE * mq_reset_spec_in_method_names (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int *continue_walk) { - if (node->node_type == PT_METHOD_CALL) + if (PT_IS_METHOD (node)) { PT_NODE *method_name; method_name = node->info.method_call.method_name; diff --git a/src/parser/xasl_generation.c b/src/parser/xasl_generation.c index b0e65d751da..0fb03e6de8c 100644 --- a/src/parser/xasl_generation.c +++ b/src/parser/xasl_generation.c @@ -66,6 +66,7 @@ #include "db_json.hpp" #include "jsp_cl.h" #include "subquery_cache.h" +#include "pl_signature.hpp" #if defined(WINDOWS) #include "wintcp.h" @@ -224,9 +225,6 @@ static void pt_fill_in_attrid_array (REGU_VARIABLE_LIST attr_list, ATTR_ID * att static SORT_LIST *pt_to_sort_list (PARSER_CONTEXT * parser, PT_NODE * node_list, PT_NODE * col_list, SORT_LIST_MODE sort_mode); -static int *pt_to_method_arglist (PARSER_CONTEXT * parser, PT_NODE * target, PT_NODE * node_list, - PT_NODE * subquery_as_attr_list); - static int regu_make_constant_vid (DB_VALUE * val, DB_VALUE ** dbvalptr); static int set_has_objs (DB_SET * seq); static int setof_mop_to_setof_vobj (PARSER_CONTEXT * parser, DB_SET * seq, DB_VALUE * new_val); @@ -237,6 +235,8 @@ static REGU_VARIABLE *pt_make_regu_constant (PARSER_CONTEXT * parser, DB_VALUE * static REGU_VARIABLE *pt_make_regu_pred (const PRED_EXPR * pred); static REGU_VARIABLE *pt_make_function (PARSER_CONTEXT * parser, int function_code, const REGU_VARIABLE_LIST arg_list, const DB_TYPE result_type, const PT_NODE * node); + +static REGU_VARIABLE *pt_stored_procedure_to_regu (PARSER_CONTEXT * parser, PT_NODE * node); static REGU_VARIABLE *pt_function_to_regu (PARSER_CONTEXT * parser, PT_NODE * function); static REGU_VARIABLE *pt_make_regu_subquery (PARSER_CONTEXT * parser, XASL_NODE * xasl, const UNBOX unbox, const PT_NODE * node); @@ -334,7 +334,7 @@ static int pt_fix_buildlist_aggregate_cume_dist_percent_rank (PARSER_CONTEXT * p ((r)->type == TYPE_CONSTANT || (r)->type == TYPE_DBVAL || (r)->type == TYPE_POS_VALUE || (r)->type == TYPE_INARITH) #define VALIDATE_REGU_KEY(r) \ - ((r)->type == TYPE_CONSTANT || (r)->type == TYPE_DBVAL || (r)->type == TYPE_POS_VALUE \ + ((r)->type == TYPE_CONSTANT || (r)->type == TYPE_DBVAL || (r)->type == TYPE_POS_VALUE || (r)->type == TYPE_SP \ || ((r)->type == TYPE_INARITH && validate_regu_key_function_index ((r)))) typedef struct xasl_supp_info @@ -552,7 +552,7 @@ static ACCESS_SPEC_TYPE *pt_make_showstmt_access_spec (PRED_EXPR * where_pred, S static ACCESS_SPEC_TYPE *pt_make_set_access_spec (REGU_VARIABLE * set_expr, ACCESS_METHOD access, INDX_INFO * indexptr, PRED_EXPR * where_pred, REGU_VARIABLE_LIST attr_list); -static ACCESS_SPEC_TYPE *pt_make_cselect_access_spec (XASL_NODE * xasl, METHOD_SIG_LIST * method_sig_list, +static ACCESS_SPEC_TYPE *pt_make_cselect_access_spec (XASL_NODE * xasl, PL_SIGNATURE_ARRAY_TYPE * sig_array, ACCESS_METHOD access, INDX_INFO * indexptr, PRED_EXPR * where_pred, REGU_VARIABLE_LIST attr_list); @@ -568,9 +568,6 @@ static PT_NODE *pt_build_do_stmt_aptr_list_pre (PARSER_CONTEXT * parser, PT_NODE static XASL_NODE *pt_build_do_stmt_aptr_list (PARSER_CONTEXT * parser, PT_NODE * node); -static METHOD_SIG_LIST *pt_to_method_sig_list (PARSER_CONTEXT * parser, PT_NODE * node_list, - PT_NODE * subquery_as_attr_list); - static int pt_is_subquery (PT_NODE * node); static int *pt_make_identity_offsets (PT_NODE * attr_list); @@ -3753,220 +3750,6 @@ pt_filter_pseudo_specs (PARSER_CONTEXT * parser, PT_NODE * spec) return spec; } -/* - * pt_to_method_arglist () - converts a parse expression tree list of - * method call arguments to method argument array - * return: A NULL on error occurred - * parser(in): - * target(in): - * node_list(in): should be parse name nodes - * subquery_as_attr_list(in): - */ -static int * -pt_to_method_arglist (PARSER_CONTEXT * parser, PT_NODE * target, PT_NODE * node_list, PT_NODE * subquery_as_attr_list) -{ - int *arg_list = NULL; - int i = 1; - int num_args = pt_length_of_list (node_list) + 1; - PT_NODE *node; - - arg_list = regu_int_array_alloc (num_args); - if (!arg_list) - { - return NULL; - } - - if (target != NULL) - { - /* the method call target is the first element in the array */ - arg_list[0] = pt_find_attribute (parser, target, subquery_as_attr_list); - if (arg_list[0] == -1) - { - return NULL; - } - } - else - { - i = 0; - } - - for (node = node_list; node != NULL; node = node->next) - { - arg_list[i] = pt_find_attribute (parser, node, subquery_as_attr_list); - if (arg_list[i] == -1) - { - return NULL; - } - i++; - } - - return arg_list; -} - - -/* - * pt_to_method_sig_list () - converts a parse expression tree list of - * method calls to method signature list - * return: A NULL return indicates a (memory) error occurred - * parser(in): - * node_list(in): should be parse method nodes - * subquery_as_attr_list(in): - */ -static METHOD_SIG_LIST * -pt_to_method_sig_list (PARSER_CONTEXT * parser, PT_NODE * node_list, PT_NODE * subquery_as_attr_list) -{ - METHOD_SIG_LIST *sig_list = NULL; - METHOD_SIG **tail = NULL; - PT_NODE *node; - - regu_alloc (sig_list); - if (!sig_list) - { - return NULL; - } - - tail = &(sig_list->method_sig); - - for (node = node_list; node != NULL; node = node->next) - { - regu_alloc (*tail); - - if (*tail) - { - (sig_list->num_methods)++; - - (*tail)->method_name = (char *) node->info.method_call.method_name->info.name.original; - - /* num_method_args does not include the target by convention */ - (*tail)->num_method_args = pt_length_of_list (node->info.method_call.arg_list); - (*tail)->method_arg_pos = - pt_to_method_arglist (parser, node->info.method_call.on_call_target, node->info.method_call.arg_list, - subquery_as_attr_list); - - if (PT_IS_METHOD (node)) - { - PT_NODE *dt = node->info.method_call.on_call_target->data_type; - /* beware of virtual classes */ - if (dt->info.data_type.virt_object) - { - (*tail)->class_name = (char *) db_get_class_name (dt->info.data_type.virt_object); - } - else - { - (*tail)->class_name = (char *) dt->info.data_type.entity->info.name.original; - } - - (*tail)->method_type = PT_IS_CLASS_METHOD (node) ? METHOD_TYPE_CLASS_METHOD : METHOD_TYPE_INSTANCE_METHOD; - } - else if (PT_IS_JAVA_SP (node)) - { - (*tail)->class_name = NULL; - (*tail)->method_type = METHOD_TYPE_JAVA_SP; - - int num_args = (*tail)->num_method_args; - (*tail)->arg_info.arg_mode = regu_int_array_alloc (num_args); - (*tail)->arg_info.arg_type = regu_int_array_alloc (num_args); - - DB_OBJECT *mop_p = jsp_find_stored_procedure ((*tail)->method_name); - if (mop_p) - { - /* java stored procedure signature */ - DB_VALUE method; - if (db_get (mop_p, SP_ATTR_TARGET, &method) == NO_ERROR) - { - (*tail)->method_name = (char *) db_get_string (&method); - } - else - { - break; - } - - DB_VALUE args; - /* arg_mode, arg_type */ - if (db_get (mop_p, SP_ATTR_ARGS, &args) == NO_ERROR) - { - DB_SET *param_set = db_get_set (&args); - DB_VALUE mode, type, temp; - int i, arg_mode, arg_type; - for (i = 0; i < num_args; i++) - { - set_get_element (param_set, i, &temp); - DB_OBJECT *arg_mop_p = db_get_object (&temp); - if (arg_mop_p) - { - if (db_get (arg_mop_p, SP_ATTR_MODE, &mode) == NO_ERROR) - { - arg_mode = db_get_int (&mode); - } - - if (db_get (arg_mop_p, SP_ATTR_DATA_TYPE, &type) == NO_ERROR) - { - arg_type = db_get_int (&type); - } - - (*tail)->arg_info.arg_mode[i] = arg_mode; - (*tail)->arg_info.arg_type[i] = arg_type; - - pr_clear_value (&mode); - pr_clear_value (&type); - pr_clear_value (&temp); - } - else - { - break; - } - - - if (jsp_check_out_param_in_query (parser, node, arg_mode) != NO_ERROR) - { - pr_clear_value (&args); - return NULL; - } - } - pr_clear_value (&args); - } - else - { - break; - } - - /* result type */ - DB_VALUE result_type; - if (db_get (mop_p, SP_ATTR_RETURN_TYPE, &result_type) == NO_ERROR) - { - (*tail)->arg_info.result_type = db_get_int (&result_type); - pr_clear_value (&result_type); - } - else - { - break; - } - } - else - { - break; - } - } - else - { - /* should be never happened */ - assert (false); - break; - } - tail = &(*tail)->next; - } - else - { - /* something failed */ - sig_list = NULL; - assert (false); - break; - } - } - - return sig_list; -} - /* * pt_make_val_list () - Makes a val list with a DB_VALUE place holder * for every attribute on an attribute list @@ -4560,7 +4343,7 @@ pt_to_aggregate_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *c /* Do not proceed down the leaves. */ *continue_walk = PT_LIST_WALK; } - else if (tree->node_type == PT_METHOD_CALL) + else if (PT_IS_METHOD (tree)) { /* Do not proceed down the leaves */ *continue_walk = PT_LIST_WALK; @@ -5019,6 +4802,10 @@ pt_cnt_attrs (const REGU_VARIABLE_LIST attr_list) /* need to check all the operands for the function */ cnt += pt_cnt_attrs (tmp->value.value.funcp->operand); } + else if (tmp->value.type == TYPE_SP) + { + cnt += pt_cnt_attrs (tmp->value.value.sp_ptr->args); + } } return cnt; @@ -5052,6 +4839,10 @@ pt_fill_in_attrid_array (REGU_VARIABLE_LIST attr_list, ATTR_ID * attr_array, int /* need to check all the operands for the function */ pt_fill_in_attrid_array (tmp->value.value.funcp->operand, attr_array, next_pos); } + else if (tmp->value.type == TYPE_SP) + { + pt_fill_in_attrid_array (tmp->value.value.sp_ptr->args, attr_array, next_pos); + } } } @@ -5420,14 +5211,14 @@ pt_make_set_access_spec (REGU_VARIABLE * set_expr, ACCESS_METHOD access, INDX_IN * ACCESS_SPEC_TYPE TARGET_METHOD structure * return: * xasl(in): - * method_sig_list(in): + * sig_array(in): * access(in): * indexptr(in): * where_pred(in): * attr_list(in): */ static ACCESS_SPEC_TYPE * -pt_make_cselect_access_spec (XASL_NODE * xasl, METHOD_SIG_LIST * method_sig_list, ACCESS_METHOD access, +pt_make_cselect_access_spec (XASL_NODE * xasl, PL_SIGNATURE_ARRAY_TYPE * sig_array, ACCESS_METHOD access, INDX_INFO * indexptr, PRED_EXPR * where_pred, REGU_VARIABLE_LIST attr_list) { ACCESS_SPEC_TYPE *spec; @@ -5443,7 +5234,7 @@ pt_make_cselect_access_spec (XASL_NODE * xasl, METHOD_SIG_LIST * method_sig_list { spec->s.method_node.method_regu_list = attr_list; spec->s.method_node.xasl_node = xasl; - spec->s.method_node.method_sig_list = method_sig_list; + spec->s.method_node.sig_array = sig_array; } return spec; @@ -6846,6 +6637,58 @@ pt_make_function (PARSER_CONTEXT * parser, int function_code, const REGU_VARIABL } +/* + * pt_stored_procedure_to_regu () - takes a PT_METHOD_CALL and converts to a regu_variable + * return: A NULL return indicates an error occurred + * parser(in): + * function(in/out): + * + */ +static REGU_VARIABLE * +pt_stored_procedure_to_regu (PARSER_CONTEXT * parser, PT_NODE * node) +{ + int error = NO_ERROR; + REGU_VARIABLE *regu = NULL; + REGU_VARIABLE_LIST args; + SP_TYPE *sp = NULL; + + regu_alloc (regu); + if (!regu) + { + return NULL; + } + + regu_alloc (regu->value.sp_ptr); + + sp = regu->value.sp_ptr; + if (sp) + { + error = jsp_make_pl_signature (parser, node, NULL, *(sp->sig)); + if (error != NO_ERROR) + { + return NULL; + } + + PT_NODE *default_next_node_list = jsp_get_default_expr_node_list (parser, *(sp->sig)); + node->info.method_call.arg_list = parser_append_node (default_next_node_list, node->info.method_call.arg_list); + + DB_TYPE result_type = (DB_TYPE) sp->sig->result_type; + if (result_type == DB_TYPE_RESULTSET) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_RETURN_RESULTSET, 0); + return NULL; + } + + regu_dbval_type_init (sp->value, result_type); + sp->args = pt_to_regu_variable_list (parser, node->info.method_call.arg_list, UNBOX_AS_VALUE, NULL, NULL); + } + + regu->type = TYPE_SP; + regu->domain = pt_xasl_node_to_domain (parser, node); + + return regu; +} + /* * pt_function_to_regu () - takes a PT_FUNCTION and converts to a regu_variable * return: A NULL return indicates an error occurred @@ -7729,11 +7572,24 @@ pt_to_regu_variable (PARSER_CONTEXT * parser, PT_NODE * node, UNBOX unbox) */ /* a method call that can be evaluated as a constant expression. */ - regu_alloc (val); - pt_evaluate_tree (parser, node, val, 1); - if (!pt_has_error (parser)) + if (PT_IS_METHOD (node)) { - regu = pt_make_regu_constant (parser, val, pt_node_to_db_type (node), node); + /* a method call that can be evaluated as a constant expression. */ + regu_alloc (val); + pt_evaluate_tree (parser, node, val, 1); + if (!pt_has_error (parser)) + { + regu = pt_make_regu_constant (parser, val, pt_node_to_db_type (node), node); + } + } + else + { + regu = pt_stored_procedure_to_regu (parser, node); + if (regu == NULL) + { + PT_ERRORc (parser, node, er_msg ()); + } + return regu; } break; @@ -10874,11 +10730,12 @@ pt_to_list_key (PARSER_CONTEXT * parser, PT_NODE ** term_exprs, int nterms, bool { /* PT_IS_IN or PT_EQ_SOME */ - if (rhs->node_type == PT_FUNCTION) + if (rhs->node_type == PT_FUNCTION || rhs->node_type == PT_METHOD_CALL) { /* PT_FUNCTION */ + elem = (rhs->node_type == PT_FUNCTION) ? rhs->info.function.arg_list : rhs->info.method_call.arg_list; - for (j = 0, elem = rhs->info.function.arg_list; j < n_elem && elem; j++, elem = elem->next) + for (j = 0; j < n_elem && elem; j++, elem = elem->next) { regu_var_list[j] = pt_to_regu_variable (parser, elem, UNBOX_AS_VALUE); @@ -12907,30 +12764,42 @@ pt_to_cselect_table_spec_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE XASL_NODE *subquery_proc; REGU_VARIABLE_LIST regu_attributes; ACCESS_SPEC_TYPE *access; - METHOD_SIG_LIST *method_sig_list; + PL_SIGNATURE_ARRAY_TYPE *sig_array; + int idx = 0; /* every cselect must have a subquery for its source list file, this is pointed to by the methods of the cselect */ - if (!cselect || !(cselect->node_type == PT_METHOD_CALL) || !src_derived_tbl || !PT_SPEC_IS_DERIVED (src_derived_tbl)) + if (!cselect || !(PT_IS_METHOD (cselect)) || !src_derived_tbl || !PT_SPEC_IS_DERIVED (src_derived_tbl)) { return NULL; } subquery_proc = (XASL_NODE *) src_derived_tbl->info.spec.derived_table->info.query.xasl; - method_sig_list = pt_to_method_sig_list (parser, cselect, src_derived_tbl->info.spec.as_attr_list); - if (method_sig_list == NULL) + regu_new (sig_array, pt_length_of_list (cselect)); + if (sig_array == NULL) { return NULL; } + + for (PT_NODE * node = cselect; node != NULL; node = node->next) + { + int error = jsp_make_pl_signature (parser, node, src_derived_tbl->info.spec.as_attr_list, sig_array->sigs[idx]); + if (error != NO_ERROR) + { + regu_delete (sig_array); + return NULL; + } + idx++; + } + /* This generates a list of TYPE_POSITION regu_variables There information is stored in a QFILE_TUPLE_VALUE_POSITION, * which describes a type and index into a list file. */ - regu_attributes = pt_to_position_regu_variable_list (parser, spec->info.spec.as_attr_list, NULL, NULL); access = - pt_make_cselect_access_spec (subquery_proc, method_sig_list, ACCESS_METHOD_SEQUENTIAL, NULL, NULL, regu_attributes); + pt_make_cselect_access_spec (subquery_proc, sig_array, ACCESS_METHOD_SEQUENTIAL, NULL, NULL, regu_attributes); - if (access && subquery_proc && method_sig_list && (regu_attributes || !spec->info.spec.as_attr_list)) + if (access && subquery_proc && sig_array && (regu_attributes || !spec->info.spec.as_attr_list)) { return access; } @@ -23197,6 +23066,32 @@ pt_get_var_regu_variable_p_list (const REGU_VARIABLE * regu, bool is_prior, int } break; + case TYPE_SP: + { + REGU_VARIABLE_LIST r = regu->value.sp_ptr->args; + while (r) + { + list1 = pt_get_var_regu_variable_p_list (&r->value, is_prior, err); + + if (!list) + { + list = list1; + } + else + { + list2 = list; + while (list2->next) + { + list2 = list2->next; + } + list2->next = list1; + } + + r = r->next; + } + } + break; + default: break; } @@ -27749,6 +27644,8 @@ pt_make_sq_cache_key_struct (QPROC_DB_VALUE_LIST key_struct, void *p, int type) case TYPE_CLASSOID: case TYPE_REGUVAL_LIST: case TYPE_REGU_VAR_LIST: + + case TYPE_SP: /* Result Cache not supported */ return ER_FAILED; break; diff --git a/src/parser/xasl_regu_alloc.cpp b/src/parser/xasl_regu_alloc.cpp index b5dc2f6d813..607f6a83163 100644 --- a/src/parser/xasl_regu_alloc.cpp +++ b/src/parser/xasl_regu_alloc.cpp @@ -194,7 +194,7 @@ regu_spec_target_init (access_spec_node &spec, TARGET_TYPE type) case TARGET_METHOD: ACCESS_SPEC_METHOD_REGU_LIST (&spec) = NULL; ACCESS_SPEC_XASL_NODE (&spec) = NULL; - ACCESS_SPEC_METHOD_SIG_LIST (&spec) = NULL; + ACCESS_SPEC_METHOD_SIG_ARRAY (&spec) = NULL; break; case TARGET_JSON_TABLE: ACCESS_SPEC_JSON_TABLE_REGU_VAR (&spec) = NULL; @@ -280,6 +280,21 @@ regu_init (arith_list_node &arith) regu_alloc (arith.value); } +void +regu_init (cubxasl::sp_node &sp) +{ + sp.args = NULL; + sp.sig = NULL; + + regu_alloc (sp.value); + + regu_alloc (sp.sig); + if (sp.sig) + { + new (sp.sig) PL_SIGNATURE_TYPE (); + } +} + void regu_init (function_node &fnode) { diff --git a/src/parser/xasl_regu_alloc.hpp b/src/parser/xasl_regu_alloc.hpp index 1cdd07a551c..22a566c3dfb 100644 --- a/src/parser/xasl_regu_alloc.hpp +++ b/src/parser/xasl_regu_alloc.hpp @@ -72,6 +72,7 @@ void regu_init (upddel_class_info &upddel); void regu_init (update_assignment &assign); void regu_init (arith_list_node &arith); void regu_init (function_node &fnode); +void regu_init (cubxasl::sp_node &sp); void regu_init (cubxasl::aggregate_list_node &agg); void regu_init (cubxasl::analytic_list_node &ana); void regu_init (xasl_node &node); @@ -85,6 +86,12 @@ void regu_alloc (T *&ptr); template void regu_array_alloc (T **ptr, size_t size); +template +void regu_new (T *&ptr, Args &&... args); + +template +void regu_delete (T *&ptr); + /* for regu_machead_array () */ int *regu_int_array_alloc (int size); OID *regu_oid_array_alloc (int size); @@ -120,6 +127,26 @@ regu_alloc (T *&ptr) regu_init (*ptr); } +template +void +regu_new (T *&ptr, Args &&... args) +{ + ptr = reinterpret_cast (pt_alloc_packing_buf ((int) sizeof (T))); + if (ptr == NULL) + { + regu_set_error_with_zero_args (ER_REGU_NO_SPACE); + return; + } + new (ptr) T (std::forward (args)...); +} + +template +void +regu_delete (T *&ptr) +{ + ptr->~T (); // call destructor, placement new in regu_new () +} + template void regu_array_alloc (T **ptr, size_t size) diff --git a/src/query/execute_schema.c b/src/query/execute_schema.c index c4e312eef36..df268c651c7 100644 --- a/src/query/execute_schema.c +++ b/src/query/execute_schema.c @@ -59,6 +59,9 @@ #include "xasl_to_stream.h" #include "parser_support.h" #include "dbtype.h" +#include "jsp_cl.h" +#include "msgcat_glossary.hpp" +#include "authenticate_access_auth.hpp" #if defined (SUPPRESS_STRLEN_WARNING) #define strlen(s1) ((int) strlen(s1)) @@ -1749,7 +1752,7 @@ do_grant (const PARSER_CONTEXT * parser, const PT_NODE * statement) DB_OBJECT *user_obj, *class_mop; PT_NODE *auth_cmd_list, *auth_list, *auth; DB_AUTH db_auth; - PT_NODE *spec_list, *s_list, *spec; + PT_NODE *spec_list; PT_NODE *entity_list, *entity; int grant_option; bool set_savepoint = false; @@ -1791,27 +1794,55 @@ do_grant (const PARSER_CONTEXT * parser, const PT_NODE * statement) { db_auth = pt_auth_to_db_auth (auth); - s_list = spec_list; - for (spec = s_list; spec != NULL; spec = spec->next) + if (auth->info.auth_cmd.auth_cmd == PT_EXECUTE_PROCEDURE_PRIV) { - entity_list = spec->info.spec.flat_entity_list; - for (entity = entity_list; entity != NULL; entity = entity->next) + // NOTE: db_auth is always DB_AUTH_EXECUTE + assert (db_auth == DB_AUTH_EXECUTE); + + PT_NODE *p_list = spec_list; + for (PT_NODE * procs = p_list; procs != NULL; procs = procs->next) { - class_mop = db_find_class (entity->info.name.original); - if (class_mop == NULL) + // [TODO] Resovle user schema name, built-in package name + const char *proc_name = procs->info.name.original; + + MOP proc_mop = jsp_find_stored_procedure (proc_name, DB_AUTH_NONE); + if (proc_mop == NULL) { assert (er_errid () != NO_ERROR); error = er_errid (); goto end; } - error = db_grant (user_obj, class_mop, db_auth, grant_option); + error = db_grant_object (DB_OBJECT_PROCEDURE, user_obj, proc_mop, db_auth, grant_option); if (error != NO_ERROR) { goto end; } } } + else + { + for (PT_NODE * spec = spec_list; spec != NULL; spec = spec->next) + { + entity_list = spec->info.spec.flat_entity_list; + for (entity = entity_list; entity != NULL; entity = entity->next) + { + class_mop = db_find_class (entity->info.name.original); + if (class_mop == NULL) + { + assert (er_errid () != NO_ERROR); + error = er_errid (); + goto end; + } + + error = db_grant_object (DB_OBJECT_CLASS, user_obj, class_mop, db_auth, grant_option); + if (error != NO_ERROR) + { + goto end; + } + } + } + } } } @@ -1871,27 +1902,56 @@ do_revoke (const PARSER_CONTEXT * parser, const PT_NODE * statement) { db_auth = pt_auth_to_db_auth (auth); - s_list = spec_list; - for (spec = s_list; spec != NULL; spec = spec->next) + if (auth->info.auth_cmd.auth_cmd == PT_EXECUTE_PROCEDURE_PRIV) { - entity_list = spec->info.spec.flat_entity_list; - for (entity = entity_list; entity != NULL; entity = entity->next) + // NOTE: db_auth is always DB_AUTH_EXECUTE + assert (db_auth == DB_AUTH_EXECUTE); + + PT_NODE *p_list = spec_list; + for (PT_NODE * procs = p_list; procs != NULL; procs = procs->next) { - class_mop = db_find_class (entity->info.name.original); - if (class_mop == NULL) + // [TODO] Resovle user schema name, built-in package name + const char *proc_name = procs->info.name.original; + + MOP proc_mop = jsp_find_stored_procedure (proc_name, DB_AUTH_NONE); + if (proc_mop == NULL) { assert (er_errid () != NO_ERROR); error = er_errid (); goto end; } - error = db_revoke (user_obj, class_mop, db_auth); + // TODO: In CBRD-24912, GRANT/REVOKE for stored procedure is implemented, the following will be processed properly + error = db_revoke_object (DB_OBJECT_PROCEDURE, user_obj, proc_mop, db_auth); if (error != NO_ERROR) { goto end; } } } + else + { + for (PT_NODE * spec = spec_list; spec != NULL; spec = spec->next) + { + entity_list = spec->info.spec.flat_entity_list; + for (entity = entity_list; entity != NULL; entity = entity->next) + { + class_mop = db_find_class (entity->info.name.original); + if (class_mop == NULL) + { + assert (er_errid () != NO_ERROR); + error = er_errid (); + goto end; + } + + error = db_revoke_object (DB_OBJECT_CLASS, user_obj, class_mop, db_auth); + if (error != NO_ERROR) + { + goto end; + } + } + } + } } } @@ -2258,7 +2318,7 @@ do_alter_user (const PARSER_CONTEXT * parser, const PT_NODE * statement) if (!ws_is_same_object (user, Au_user) && !au_is_dba_group_member (Au_user)) { error = ER_AU_NOT_OWNER; - er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_CLASS)); goto end; } @@ -10115,9 +10175,10 @@ do_alter_change_owner (PARSER_CONTEXT * const parser, PT_NODE * const alter) { int error = NO_ERROR; DB_OBJECT *obj = NULL; - MOP class_mop, user_mop; + MOP class_mop, user_mop, save_user, owner; PT_NODE *class_, *user; SM_CLASS *sm_class = NULL; + const char *table_name; assert (alter != NULL); @@ -10141,6 +10202,13 @@ do_alter_change_owner (PARSER_CONTEXT * const parser, PT_NODE * const alter) return error; } + table_name = sm_get_ch_name (class_mop); + if (table_name == NULL) + { + ASSERT_ERROR_AND_SET (error); + return error; + } + /* To change the owner of a system class is not allowed. */ if (sm_issystem (sm_class)) { @@ -10148,6 +10216,28 @@ do_alter_change_owner (PARSER_CONTEXT * const parser, PT_NODE * const alter) return error; } + /* when changing the owner, all privileges are revoked */ + owner = au_get_class_owner (class_mop); + if (owner == NULL) + { + assert (er_errid () != NO_ERROR); + error = er_errid (); + return error; + } + + save_user = Au_user; + if (AU_SET_USER (owner) == NO_ERROR) + { + error = au_object_revoke_all_privileges (DB_OBJECT_CLASS, owner, table_name); + if (error != NO_ERROR) + { + AU_SET_USER (save_user); + return error; + } + } + + AU_SET_USER (save_user); + user_mop = au_find_user (user->info.name.original); if (user_mop == NULL) { diff --git a/src/query/execute_statement.c b/src/query/execute_statement.c index a554d8eaf22..e533f0d00be 100644 --- a/src/query/execute_statement.c +++ b/src/query/execute_statement.c @@ -20250,6 +20250,98 @@ do_find_synonym_by_query (const char *name, char *buf, int buf_size) #undef QUERY_BUF_SIZE } +int +do_find_stored_procedure_by_query (const char *name, char *buf, int buf_size) +{ +#define QUERY_BUF_SIZE 2048 + DB_QUERY_RESULT *query_result = NULL; + DB_QUERY_ERROR query_error; + DB_VALUE value; + const char *query = NULL; + char query_buf[QUERY_BUF_SIZE] = { '\0' }; + const char *current_schema_name = NULL; + const char *sp_name = NULL; + int error = NO_ERROR; + + db_make_null (&value); + query_error.err_lineno = 0; + query_error.err_posno = 0; + + if (name == NULL || name[0] == '\0') + { + ERROR_SET_WARNING (error, ER_OBJ_INVALID_ARGUMENTS); + return error; + } + + assert (buf != NULL); + + current_schema_name = sc_current_schema_name (); + + sp_name = sm_remove_qualifier_name (name); + query = "SELECT [unique_name] FROM [%s] WHERE [sp_name] = '%s' AND [owner].[name] != UPPER ('%s')"; + assert (QUERY_BUF_SIZE > snprintf (NULL, 0, query, CT_STORED_PROC_NAME, sp_name, current_schema_name)); + snprintf (query_buf, QUERY_BUF_SIZE, query, CT_STORED_PROC_NAME, sp_name, current_schema_name); + assert (query_buf[0] != '\0'); + + error = db_compile_and_execute_local (query_buf, &query_result, &query_error); + if (error < NO_ERROR) + { + ASSERT_ERROR (); + goto end; + } + + error = db_query_first_tuple (query_result); + if (error != DB_CURSOR_SUCCESS) + { + if (error == DB_CURSOR_END) + { + ERROR_SET_WARNING_1ARG (error, ER_SP_NOT_EXIST, name); + } + else + { + ASSERT_ERROR (); + } + + goto end; + } + + error = db_query_get_tuple_value (query_result, 0, &value); + if (error != NO_ERROR) + { + ASSERT_ERROR (); + goto end; + } + + if (!DB_IS_NULL (&value)) + { + assert (strlen (db_get_string (&value)) < buf_size); + strcpy (buf, db_get_string (&value)); + } + else + { + /* unique_name must not be null. */ + ASSERT_ERROR_AND_SET (error); + goto end; + } + + error = db_query_next_tuple (query_result); + if (error != DB_CURSOR_END) + { + /* No result can be returned because unique_name is not unique. */ + buf[0] = '\0'; + } + +end: + if (query_result) + { + db_query_end (query_result); + query_result = NULL; + } + + return error; +#undef QUERY_BUF_SIZE +} + /* * do_set_trace_to_query_flag() - * return: void diff --git a/src/query/execute_statement.h b/src/query/execute_statement.h index d7d2863f179..31c14f4de2f 100644 --- a/src/query/execute_statement.h +++ b/src/query/execute_statement.h @@ -207,4 +207,5 @@ extern int do_find_class_by_query (const char *name, char *buf, int buf_size); extern int do_find_serial_by_query (const char *name, char *buf, int buf_size); extern int do_find_trigger_by_query (const char *name, char *buf, int buf_size); extern int do_find_synonym_by_query (const char *name, char *buf, int buf_size); +extern int do_find_stored_procedure_by_query (const char *name, char *buf, int buf_size); #endif /* _EXECUTE_STATEMENT_H_ */ diff --git a/src/query/fetch.c b/src/query/fetch.c index d78d38d411c..5f434052d71 100644 --- a/src/query/fetch.c +++ b/src/query/fetch.c @@ -54,11 +54,11 @@ #include "query_executor.h" #include "thread_entry.hpp" #include "subquery_cache.h" +#include "pl_executor.hpp" #include "dbtype.h" // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" - static int fetch_peek_arith (THREAD_ENTRY * thread_p, REGU_VARIABLE * regu_var, val_descr * vd, OID * obj_oid, QFILE_TUPLE tpl, DB_VALUE ** peek_dbval); static int fetch_peek_dbval_pos (REGU_VARIABLE * regu_var, QFILE_TUPLE tpl, int pos, DB_VALUE ** peek_dbval, @@ -1210,6 +1210,37 @@ fetch_peek_arith (THREAD_ENTRY * thread_p, REGU_VARIABLE * regu_var, val_descr * { PRIM_SET_NULL (arithptr->value); } + else if (DB_VALUE_DOMAIN_TYPE (peek_right) == DB_TYPE_BLOB) + { + DB_VALUE tval; + + db_make_null (&tval); + dom_status = tp_value_cast (peek_right, &tval, &tp_VarBit_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, peek_right, &tp_VarBit_domain); + db_value_clear (&tval); + goto error; + } + + db_make_int (arithptr->value, db_get_string_size (&tval)); + db_value_clear (&tval); + } + else if (!TP_IS_STRING_TYPE (DB_VALUE_TYPE (peek_right))) + { + DB_VALUE tval; + + db_make_null (&tval); + dom_status = tp_value_cast (peek_right, &tval, &tp_Char_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, peek_right, &tp_Char_domain); + db_value_clear (&tval); + goto error; + } + db_make_int (arithptr->value, db_get_string_size (&tval)); + db_value_clear (&tval); + } else { db_make_int (arithptr->value, db_get_string_size (peek_right)); @@ -1228,6 +1259,39 @@ fetch_peek_arith (THREAD_ENTRY * thread_p, REGU_VARIABLE * regu_var, val_descr * db_get_bit (peek_right, &len); db_make_int (arithptr->value, len); } + else if (DB_VALUE_DOMAIN_TYPE (peek_right) == DB_TYPE_BLOB) + { + DB_VALUE tval; + int len = 0; + + db_make_null (&tval); + dom_status = tp_value_cast (peek_right, &tval, &tp_VarBit_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, peek_right, &tp_VarBit_domain); + db_value_clear (&tval); + goto error; + } + + db_get_bit (&tval, &len); + db_make_int (arithptr->value, len); + db_value_clear (&tval); + } + else if (!TP_IS_CHAR_TYPE (DB_VALUE_TYPE (peek_right))) + { + DB_VALUE tval; + + db_make_null (&tval); + dom_status = tp_value_cast (peek_right, &tval, &tp_Char_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, peek_right, &tp_Char_domain); + db_value_clear (&tval); + goto error; + } + db_make_int (arithptr->value, 8 * db_get_string_size (&tval)); + db_value_clear (&tval); + } else { /* must be a char string type */ @@ -4023,6 +4087,30 @@ fetch_peek_dbval (THREAD_ENTRY * thread_p, REGU_VARIABLE * regu_var, val_descr * || REGU_VARIABLE_IS_FLAGED (regu_var, REGU_VARIABLE_FETCH_NOT_CONST)); break; + case TYPE_SP: /* fetch stored procedure value */ + { + /* clear any value from a previous iteration */ + pr_clear_value (regu_var->value.sp_ptr->value); + fetch_force_not_const_recursive (*regu_var); + + cubpl::executor executor (*regu_var->value.sp_ptr->sig); + + error = executor.fetch_args_peek (regu_var->value.sp_ptr->args, vd, obj_oid, tpl); + if (error != NO_ERROR) + { + goto exit_on_error; + } + + error = executor.execute (*regu_var->value.sp_ptr->value); + if (error != NO_ERROR) + { + goto exit_on_error; + } + + *peek_dbval = regu_var->value.sp_ptr->value; + } + break; + case TYPE_FUNC: /* fetch function value */ if (REGU_VARIABLE_IS_FLAGED (regu_var, REGU_VARIABLE_FETCH_ALL_CONST)) { @@ -4957,6 +5045,7 @@ fetch_force_not_const_recursive (REGU_VARIABLE & reguvar) case TYPE_INARITH: case TYPE_OUTARITH: case TYPE_FUNC: + case TYPE_SP: REGU_VARIABLE_SET_FLAG (®u, REGU_VARIABLE_FETCH_NOT_CONST); break; default: diff --git a/src/query/query_dump.c b/src/query/query_dump.c index 64b3d873a34..e9826546555 100644 --- a/src/query/query_dump.c +++ b/src/query/query_dump.c @@ -1145,6 +1145,8 @@ qdump_regu_type_string (REGU_DATATYPE type) return "TYPE_REGUVAL_LIST"; case TYPE_REGU_VAR_LIST: return "TYPE_REGU_VAR_LIST"; + case TYPE_SP: + return "TYPE_SP"; default: return "undefined"; } @@ -1357,6 +1359,13 @@ qdump_print_value (REGU_VARIABLE * value_p) qdump_print_function_value (value_p); return true; + case TYPE_SP: + fprintf (foutput, "[TYPE_SP]"); + fprintf (foutput, "[%s]", value_p->value.sp_ptr->sig->name); + fprintf (foutput, "args-->"); + qdump_print_regu_variable_list (value_p->value.sp_ptr->args); + return true; + default: return true; } diff --git a/src/query/query_executor.c b/src/query/query_executor.c index 3e91c069437..b2200099d3a 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -1590,6 +1590,15 @@ qexec_clear_regu_var (THREAD_ENTRY * thread_p, XASL_NODE * xasl_p, REGU_VARIABLE case TYPE_OUTARITH: pg_cnt += qexec_clear_arith_list (thread_p, xasl_p, regu_var->value.arithptr, is_final); break; + case TYPE_SP: + pr_clear_value (regu_var->value.sp_ptr->value); + pg_cnt += qexec_clear_regu_list (thread_p, xasl_p, regu_var->value.sp_ptr->args, is_final); + if (is_final) + { + delete regu_var->value.sp_ptr->sig; + regu_var->value.sp_ptr->sig = nullptr; + } + break; case TYPE_FUNC: pr_clear_value (regu_var->value.funcp->value); pg_cnt += qexec_clear_regu_list (thread_p, xasl_p, regu_var->value.funcp->operand, is_final); @@ -2101,6 +2110,11 @@ qexec_clear_access_spec_list (THREAD_ENTRY * thread_p, XASL_NODE * xasl_p, ACCES break; case TARGET_METHOD: pg_cnt += qexec_clear_regu_list (thread_p, xasl_p, p->s.method_node.method_regu_list, is_final); + if (is_final) + { + delete p->s.method_node.sig_array; + p->s.method_node.sig_array = NULL; + } break; case TARGET_REGUVAL_LIST: break; @@ -9326,7 +9340,7 @@ qexec_open_scan (THREAD_ENTRY * thread_p, ACCESS_SPEC_TYPE * curr_spec, VAL_LIST case TARGET_METHOD: error_code = scan_open_method_scan (thread_p, s_id, grouped, curr_spec->single_fetch, curr_spec->s_dbval, val_list, vd, - ACCESS_SPEC_METHOD_LIST_ID (curr_spec), ACCESS_SPEC_METHOD_SIG_LIST (curr_spec)); + ACCESS_SPEC_METHOD_LIST_ID (curr_spec), ACCESS_SPEC_METHOD_SIG_ARRAY (curr_spec)); if (error_code != NO_ERROR) { ASSERT_ERROR (); @@ -10155,6 +10169,10 @@ qexec_reset_regu_variable (REGU_VARIABLE * var) qexec_reset_regu_variable (var->value.arithptr->thirdptr); /* use arithptr */ break; + case TYPE_SP: + /* use sp_ptr */ + qexec_reset_regu_variable_list (var->value.sp_ptr->args); + break; case TYPE_FUNC: /* use funcp */ qexec_reset_regu_variable_list (var->value.funcp->operand); @@ -18854,6 +18872,17 @@ qexec_replace_prior_regu_vars_prior_expr (THREAD_ENTRY * thread_p, regu_variable qexec_replace_prior_regu_vars_prior_expr (thread_p, regu->value.arithptr->thirdptr, xasl, connect_by_ptr); break; + case TYPE_SP: + { + REGU_VARIABLE_LIST r = regu->value.sp_ptr->args; + while (r) + { + qexec_replace_prior_regu_vars_prior_expr (thread_p, &r->value, xasl, connect_by_ptr); + r = r->next; + } + } + break; + case TYPE_FUNC: { REGU_VARIABLE_LIST r = regu->value.funcp->operand; @@ -18901,6 +18930,17 @@ qexec_replace_prior_regu_vars (THREAD_ENTRY * thread_p, REGU_VARIABLE * regu, XA } break; + case TYPE_SP: + { + REGU_VARIABLE_LIST r = regu->value.sp_ptr->args; + while (r) + { + qexec_replace_prior_regu_vars (thread_p, &r->value, xasl); + r = r->next; + } + } + break; + case TYPE_FUNC: { REGU_VARIABLE_LIST r = regu->value.funcp->operand; diff --git a/src/query/regu_var.cpp b/src/query/regu_var.cpp index 9103a55a8bc..13e5f91433a 100644 --- a/src/query/regu_var.cpp +++ b/src/query/regu_var.cpp @@ -65,6 +65,19 @@ regu_variable_node::map_regu (const map_regu_func_type &func, bool &stop) map_regu_not_null_and_check_stop (value.arithptr->rightptr); break; + case TYPE_SP: + if (value.sp_ptr == NULL) + { + assert (false); + return; + } + + for (regu_variable_list_node *arg = value.sp_ptr->args; arg != NULL; arg = arg->next) + { + map_regu_and_check_stop (&arg->value); + } + break; + case TYPE_FUNC: if (value.funcp == NULL) { @@ -143,6 +156,11 @@ regu_variable_node::clear_xasl_local () } break; + case TYPE_SP: + assert (value.sp_ptr != NULL); + pr_clear_value (value.sp_ptr->value); + break; + case TYPE_FUNC: assert (value.funcp != NULL); pr_clear_value (value.funcp->value); diff --git a/src/query/regu_var.hpp b/src/query/regu_var.hpp index 7311335fba8..537138d03ef 100644 --- a/src/query/regu_var.hpp +++ b/src/query/regu_var.hpp @@ -29,6 +29,7 @@ #include "string_opfunc.h" #include "object_primitive.h" #include "db_function.hpp" +#include "xasl_sp.hpp" #include @@ -58,7 +59,8 @@ typedef enum TYPE_CLASSOID, /* does not have corresponding field use current class identifier value */ TYPE_FUNC, /* use funcp */ TYPE_REGUVAL_LIST, /* use reguval_list */ - TYPE_REGU_VAR_LIST /* use regu_variable_list for 'CUME_DIST' and 'PERCENT_RANK' */ + TYPE_REGU_VAR_LIST, /* use regu_variable_list for 'CUME_DIST' and 'PERCENT_RANK' */ + TYPE_SP /* use sp_ptr */ } REGU_DATATYPE; /* declare ahead REGU_VARIABLE */ @@ -192,6 +194,7 @@ class regu_variable_node struct function_node *funcp; /* function */ REGU_VALUE_LIST *reguval_list; /* for "values" query */ REGU_VARIABLE_LIST regu_var_list; /* for CUME_DIST and PERCENT_RANK */ + cubxasl::sp_node *sp_ptr; /* stored procedure */ } value; regu_variable_node () = default; diff --git a/src/query/scan_manager.c b/src/query/scan_manager.c index 51400b0fb22..59825007c34 100644 --- a/src/query/scan_manager.c +++ b/src/query/scan_manager.c @@ -4022,7 +4022,7 @@ scan_open_method_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id, int grouped, QPROC_SINGLE_FETCH single_fetch, DB_VALUE * join_dbval, val_list_node * val_list, VAL_DESCR * vd, /* */ - QFILE_LIST_ID * list_id, method_sig_list * meth_sig_list) + QFILE_LIST_ID * list_id, PL_SIGNATURE_ARRAY_TYPE * sig_array) { /* scan type is METHOD SCAN */ scan_id->type = S_METHOD_SCAN; @@ -4031,7 +4031,7 @@ scan_open_method_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id, /* mvcc_select_lock_needed = false, fixed = true */ scan_init_scan_id (scan_id, false, S_SELECT, true, grouped, single_fetch, join_dbval, val_list, vd); - int error = scan_id->s.msid.init (thread_p, meth_sig_list, list_id); + int error = scan_id->s.msid.init (thread_p, sig_array, list_id); if (error == NO_ERROR) { error = scan_id->s.msid.open (); @@ -5216,6 +5216,8 @@ scan_next_heap_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id) regu_variable_list_node *p; hsidp = &scan_id->s.hsid; + p_current_oid = &hsidp->curr_oid; + if (scan_id->mvcc_select_lock_needed) { COPY_OID (¤t_oid, &hsidp->curr_oid); diff --git a/src/query/scan_manager.h b/src/query/scan_manager.h index a5e930600dc..28353995218 100644 --- a/src/query/scan_manager.h +++ b/src/query/scan_manager.h @@ -52,7 +52,6 @@ struct indx_info; typedef struct indx_info INDX_INFO; struct key_range; struct key_val_range; -struct method_sig_list; struct regu_variable_list_node; struct val_descr; @@ -475,7 +474,7 @@ extern int scan_open_method_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id, int grouped, QPROC_SINGLE_FETCH single_fetch, DB_VALUE * join_dbval, val_list_node * val_list, val_descr * vd, /* */ - QFILE_LIST_ID * list_id, method_sig_list * meth_sig_list); + QFILE_LIST_ID * list_id, PL_SIGNATURE_ARRAY_TYPE * meth_sig_list); extern int scan_open_dblink_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id, struct access_spec_node *spec, diff --git a/src/query/stream_to_xasl.c b/src/query/stream_to_xasl.c index 8227b1a2c1a..cbe98f4c96b 100644 --- a/src/query/stream_to_xasl.c +++ b/src/query/stream_to_xasl.c @@ -42,11 +42,14 @@ #include "xasl_predicate.hpp" #include "xasl_stream.hpp" #include "xasl_unpack_info.hpp" +#include "pl_signature.hpp" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" static ACCESS_SPEC_TYPE *stx_restore_access_spec_type (THREAD_ENTRY * thread_p, char **ptr, void *arg); static AGGREGATE_TYPE *stx_restore_aggregate_type (THREAD_ENTRY * thread_p, char *ptr); +static SP_TYPE *stx_restore_sp_type (THREAD_ENTRY * thread_p, char *ptr); static FUNCTION_TYPE *stx_restore_function_type (THREAD_ENTRY * thread_p, char *ptr); static ANALYTIC_TYPE *stx_restore_analytic_type (THREAD_ENTRY * thread_p, char *ptr); static ANALYTIC_EVAL_TYPE *stx_restore_analytic_eval_type (THREAD_ENTRY * thread_p, char *ptr); @@ -76,8 +79,10 @@ static HEAP_CACHE_ATTRINFO *stx_restore_cache_attrinfo (THREAD_ENTRY * thread_p, static DB_VALUE **stx_restore_db_value_array_extra (THREAD_ENTRY * thread_p, char *ptr, int size, int total_size); static int *stx_restore_int_array (THREAD_ENTRY * thread_p, char *ptr, int size); static OID *stx_restore_OID_array (THREAD_ENTRY * thread_p, char *ptr, int size); -static METHOD_SIG_LIST *stx_restore_method_sig_list (THREAD_ENTRY * thread_p, char *ptr); -static METHOD_SIG *stx_restore_method_sig (THREAD_ENTRY * thread_p, char *ptr, int size); + +static PL_SIGNATURE_ARRAY_TYPE *stx_restore_pl_sig_array (THREAD_ENTRY * thread_p, char *ptr); +static PL_SIGNATURE_TYPE *stx_restore_pl_sig (THREAD_ENTRY * thread_p, char *ptr); + static KEY_RANGE *stx_restore_key_range_array (THREAD_ENTRY * thread_p, char *ptr, int size); static char *stx_build_xasl_node (THREAD_ENTRY * thread_p, char *tmp, XASL_NODE * ptr); @@ -87,8 +92,10 @@ static char *stx_build_func_pred (THREAD_ENTRY * thread_p, char *tmp, FUNC_PRED static char *stx_build_cache_attrinfo (char *tmp); static char *stx_build_list_id (THREAD_ENTRY * thread_p, char *tmp, QFILE_LIST_ID * ptr); static char *stx_build_sub_xasl_id (THREAD_ENTRY * thread_p, char *tmp, XASL_ID * ptr); -static char *stx_build_method_sig_list (THREAD_ENTRY * thread_p, char *tmp, METHOD_SIG_LIST * ptr); -static char *stx_build_method_sig (THREAD_ENTRY * thread_p, char *tmp, METHOD_SIG * ptr, int size); + +static char *stx_build_pl_sig (THREAD_ENTRY * thread_p, char *ptr, PL_SIGNATURE_TYPE * sig); +static char *stx_build_pl_sig_array (THREAD_ENTRY * thread_p, char *ptr, PL_SIGNATURE_ARRAY_TYPE * sig_array); + static char *stx_build_union_proc (THREAD_ENTRY * thread_p, char *tmp, UNION_PROC_NODE * ptr); static char *stx_build_fetch_proc (THREAD_ENTRY * thread_p, char *tmp, FETCH_PROC_NODE * ptr); static char *stx_build_buildlist_proc (THREAD_ENTRY * thread_p, char *tmp, BUILDLIST_PROC_NODE * ptr); @@ -140,6 +147,7 @@ static char *stx_build_srlist_id (THREAD_ENTRY * thread_p, char *tmp, QFILE_SORT static char *stx_build_sort_list (THREAD_ENTRY * thread_p, char *tmp, SORT_LIST * ptr); static char *stx_build_connectby_proc (THREAD_ENTRY * thread_p, char *tmp, CONNECTBY_PROC_NODE * ptr); static char *stx_build_sq_cache (THREAD_ENTRY * thread_p, char *ptr, SQ_CACHE ** sq_cache_p); +static char *stx_build_sp_type (THREAD_ENTRY * thread_p, char *tmp, SP_TYPE * ptr); static REGU_VALUE_LIST *stx_regu_value_list_alloc_and_init (THREAD_ENTRY * thread_p); static REGU_VALUE_ITEM *stx_regu_value_item_alloc_and_init (THREAD_ENTRY * thread_p); @@ -424,6 +432,37 @@ stx_restore_aggregate_type (THREAD_ENTRY * thread_p, char *ptr) return aggregate; } +static SP_TYPE * +stx_restore_sp_type (THREAD_ENTRY * thread_p, char *ptr) +{ + SP_TYPE *sp; + + if (ptr == NULL) + { + return NULL; + } + + sp = (SP_TYPE *) stx_get_struct_visited_ptr (thread_p, ptr); + if (sp != NULL) + { + return sp; + } + + sp = (SP_TYPE *) stx_alloc_struct (thread_p, sizeof (*sp)); + if (sp == NULL) + { + stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); + return NULL; + } + + if (stx_mark_struct_visited (thread_p, ptr, sp) == ER_FAILED || stx_build_sp_type (thread_p, ptr, sp) == NULL) + { + return NULL; + } + + return sp; +} + static FUNCTION_TYPE * stx_restore_function_type (THREAD_ENTRY * thread_p, char *ptr) { @@ -1198,74 +1237,82 @@ stx_restore_list_id (THREAD_ENTRY * thread_p, char *ptr) } /* - * stx_restore_method_sig_list () - + * stx_restore_pl_sig () - * - * Note: do not use or_unpack_method_sig_list () */ -static METHOD_SIG_LIST * -stx_restore_method_sig_list (THREAD_ENTRY * thread_p, char *ptr) +static PL_SIGNATURE_TYPE * +stx_restore_pl_sig (THREAD_ENTRY * thread_p, char *ptr) { - METHOD_SIG_LIST *method_sig_list; + PL_SIGNATURE_TYPE *sig = NULL; if (ptr == NULL) { return NULL; } - method_sig_list = (METHOD_SIG_LIST *) stx_get_struct_visited_ptr (thread_p, ptr); - if (method_sig_list != NULL) + sig = (PL_SIGNATURE_TYPE *) stx_get_struct_visited_ptr (thread_p, ptr); + if (sig != NULL) { - return method_sig_list; + return sig; } - method_sig_list = (METHOD_SIG_LIST *) stx_alloc_struct (thread_p, sizeof (METHOD_SIG_LIST)); - if (method_sig_list == NULL) - { - stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); - return NULL; - } - if (stx_mark_struct_visited (thread_p, ptr, method_sig_list) == ER_FAILED - || stx_build_method_sig_list (thread_p, ptr, method_sig_list) == NULL) + //sig_array = (PL_SIGNATURE_ARRAY_TYPE *) stx_alloc_struct (thread_p, sizeof (PL_SIGNATURE_ARRAY_TYPE)); + //if (sig_array == NULL) + // { + // stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); + // return NULL; + // } + sig = new PL_SIGNATURE_TYPE; + + // new (sig_array) PL_SIGNATURE_ARRAY_TYPE; + + if (stx_mark_struct_visited (thread_p, ptr, sig) == ER_FAILED || stx_build_pl_sig (thread_p, ptr, sig) == NULL) { return NULL; } - return method_sig_list; + return sig; } -static METHOD_SIG * -stx_restore_method_sig (THREAD_ENTRY * thread_p, char *ptr, int count) +/* + * stx_restore_pl_sig_array () - + * + */ +static PL_SIGNATURE_ARRAY_TYPE * +stx_restore_pl_sig_array (THREAD_ENTRY * thread_p, char *ptr) { - METHOD_SIG *method_sig; + PL_SIGNATURE_ARRAY_TYPE *sig_array = NULL; if (ptr == NULL) { - assert (count == 0); return NULL; } - assert (count > 0); - - method_sig = (METHOD_SIG *) stx_get_struct_visited_ptr (thread_p, ptr); - if (method_sig != NULL) + sig_array = (PL_SIGNATURE_ARRAY_TYPE *) stx_get_struct_visited_ptr (thread_p, ptr); + if (sig_array != NULL) { - return method_sig; + return sig_array; } - method_sig = (METHOD_SIG *) stx_alloc_struct (thread_p, sizeof (METHOD_SIG)); - if (method_sig == NULL) +#if 0 + sig_array = (PL_SIGNATURE_ARRAY_TYPE *) stx_alloc_struct (thread_p, sizeof (PL_SIGNATURE_ARRAY_TYPE)); + if (sig_array == NULL) { stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); return NULL; } + new (sig_array) PL_SIGNATURE_ARRAY_TYPE; +#endif + + sig_array = new PL_SIGNATURE_ARRAY_TYPE; - if (stx_mark_struct_visited (thread_p, ptr, method_sig) == ER_FAILED - || stx_build_method_sig (thread_p, ptr, method_sig, count) == NULL) + if (stx_mark_struct_visited (thread_p, ptr, sig_array) == ER_FAILED || + stx_build_pl_sig_array (thread_p, ptr, sig_array) == NULL) { return NULL; } - return method_sig; + return sig_array; } static DB_VALUE ** @@ -2521,129 +2568,30 @@ stx_build_list_id (THREAD_ENTRY * thread_p, char *ptr, QFILE_LIST_ID * listid) return NULL; } +// FIXME: use template static char * -stx_build_method_sig_list (THREAD_ENTRY * thread_p, char *ptr, METHOD_SIG_LIST * method_sig_list) +stx_build_pl_sig (THREAD_ENTRY * thread_p, char *ptr, PL_SIGNATURE_TYPE * sig) { - int offset; - XASL_UNPACK_INFO *xasl_unpack_info = get_xasl_unpack_info_ptr (thread_p); + int size, offset; - ptr = or_unpack_int (ptr, (int *) &method_sig_list->num_methods); + ptr = or_unpack_int (ptr, (int *) &size); + packing_unpacker unpacker (ptr, size); + unpacker.unpack_all (*sig); - ptr = or_unpack_int (ptr, &offset); - if (offset == 0) - { - method_sig_list->method_sig = NULL; - } - else - { - method_sig_list->method_sig = - stx_restore_method_sig (thread_p, &xasl_unpack_info->packed_xasl[offset], method_sig_list->num_methods); - if (method_sig_list->method_sig == NULL) - { - goto error; - } - } - -#if !defined(NDEBUG) - { - int i = 0; - METHOD_SIG *sig; - - for (sig = method_sig_list->method_sig; sig; sig = sig->next) - { - i++; - } - assert (method_sig_list->num_methods == i); - } -#endif - - return ptr; - -error: - stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); - return NULL; + return (char *) unpacker.get_curr_ptr (); } +// FIXME: use template static char * -stx_build_method_sig (THREAD_ENTRY * thread_p, char *ptr, METHOD_SIG * method_sig, int count) +stx_build_pl_sig_array (THREAD_ENTRY * thread_p, char *ptr, PL_SIGNATURE_ARRAY_TYPE * sig_array) { - int offset; - int num_args, n; - XASL_UNPACK_INFO *xasl_unpack_info = get_xasl_unpack_info_ptr (thread_p); + int size, offset; - method_sig->method_name = stx_restore_string (thread_p, ptr); - if (method_sig->method_name == NULL) - { - assert (false); - goto error; - } - - ptr = or_unpack_int (ptr, (int *) &method_sig->method_type); - ptr = or_unpack_int (ptr, &method_sig->num_method_args); - - num_args = method_sig->num_method_args + 1; - - method_sig->method_arg_pos = (int *) stx_alloc_struct (thread_p, sizeof (int) * num_args); - if (method_sig->method_arg_pos == NULL) - { - goto error; - } - - for (n = 0; n < num_args; n++) - { - ptr = or_unpack_int (ptr, &(method_sig->method_arg_pos[n])); - } - - if (method_sig->method_type == METHOD_TYPE_JAVA_SP) - { - method_sig->arg_info.arg_mode = (int *) stx_alloc_struct (thread_p, sizeof (int) * method_sig->num_method_args); - if (method_sig->arg_info.arg_mode == NULL) - { - goto error; - } - - method_sig->arg_info.arg_type = (int *) stx_alloc_struct (thread_p, sizeof (int) * method_sig->num_method_args); - if (method_sig->arg_info.arg_type == NULL) - { - goto error; - } + ptr = or_unpack_int (ptr, (int *) &size); + packing_unpacker unpacker (ptr, size); + unpacker.unpack_all (*sig_array); - for (n = 0; n < method_sig->num_method_args; n++) - { - ptr = or_unpack_int (ptr, &method_sig->arg_info.arg_mode[n]); - } - for (n = 0; n < method_sig->num_method_args; n++) - { - ptr = or_unpack_int (ptr, &method_sig->arg_info.arg_type[n]); - } - - ptr = or_unpack_int (ptr, &method_sig->arg_info.result_type); - } - else /* method */ - { - /* is can be null */ - method_sig->class_name = stx_restore_string (thread_p, ptr); - } - - ptr = or_unpack_int (ptr, &offset); - if (offset == 0) - { - method_sig->next = NULL; - } - else - { - method_sig->next = stx_restore_method_sig (thread_p, &xasl_unpack_info->packed_xasl[offset], count - 1); - if (method_sig->next == NULL) - { - goto error; - } - } - - return ptr; - -error: - stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); - return NULL; + return (char *) unpacker.get_curr_ptr (); } static char * @@ -5384,12 +5332,12 @@ stx_build_method_spec_type (THREAD_ENTRY * thread_p, char *ptr, METHOD_SPEC_TYPE ptr = or_unpack_int (ptr, &offset); if (offset == 0) { - method_spec->method_sig_list = NULL; + method_spec->sig_array = NULL; } else { - method_spec->method_sig_list = stx_restore_method_sig_list (thread_p, &xasl_unpack_info->packed_xasl[offset]); - if (method_spec->method_sig_list == NULL) + method_spec->sig_array = stx_restore_pl_sig_array (thread_p, &xasl_unpack_info->packed_xasl[offset]); + if (method_spec->sig_array == NULL) { stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); return NULL; @@ -5709,6 +5657,22 @@ stx_unpack_regu_variable_value (THREAD_ENTRY * thread_p, char *ptr, REGU_VARIABL } break; + case TYPE_SP: + ptr = or_unpack_int (ptr, &offset); + if (offset == 0) + { + regu_var->value.sp_ptr = NULL; + } + else + { + regu_var->value.sp_ptr = stx_restore_sp_type (thread_p, &xasl_unpack_info_p->packed_xasl[offset]); + if (regu_var->value.sp_ptr == NULL) + { + goto error; + } + } + break; + case TYPE_ATTR_ID: case TYPE_SHARED_ATTR_ID: case TYPE_CLASS_ATTR_ID: @@ -6068,6 +6032,62 @@ stx_build_aggregate_type (THREAD_ENTRY * thread_p, char *ptr, AGGREGATE_TYPE * a return NULL; } + +static char * +stx_build_sp_type (THREAD_ENTRY * thread_p, char *ptr, SP_TYPE * sp) +{ + int tmp, offset; + XASL_UNPACK_INFO *xasl_unpack_info = get_xasl_unpack_info_ptr (thread_p); + + ptr = or_unpack_int (ptr, &offset); + if (offset == 0) + { + sp->value = NULL; + } + else + { + sp->value = stx_restore_db_value (thread_p, &xasl_unpack_info->packed_xasl[offset]); + if (sp->value == NULL) + { + stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); + return NULL; + } + assert (sp->value->need_clear == false); + } + + ptr = or_unpack_int (ptr, &offset); + if (offset == 0) + { + sp->args = NULL; + } + else + { + sp->args = stx_restore_regu_variable_list (thread_p, &xasl_unpack_info->packed_xasl[offset]); + if (sp->args == NULL) + { + stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); + return NULL; + } + } + + ptr = or_unpack_int (ptr, &offset); + if (offset == 0) + { + sp->sig = NULL; + } + else + { + sp->sig = stx_restore_pl_sig (thread_p, &xasl_unpack_info->packed_xasl[offset]); + if (sp->sig == NULL) + { + stx_set_xasl_errcode (thread_p, ER_OUT_OF_VIRTUAL_MEMORY); + return NULL; + } + } + + return ptr; +} + static char * stx_build_function_type (THREAD_ENTRY * thread_p, char *ptr, FUNCTION_TYPE * function) { diff --git a/src/query/string_opfunc.c b/src/query/string_opfunc.c index 2230e1ec238..21a8bbd826a 100644 --- a/src/query/string_opfunc.c +++ b/src/query/string_opfunc.c @@ -26659,6 +26659,7 @@ db_hex (const DB_VALUE * param, DB_VALUE * result) const char *str = NULL; char *hexval = NULL; int str_size = 0, hexval_len = 0, i = 0, error_code = NO_ERROR; + DB_VALUE tval, *ptval = NULL; /* check parameters for NULL values */ if (param == NULL || result == NULL) @@ -26676,6 +26677,7 @@ db_hex (const DB_VALUE * param, DB_VALUE * result) /* compute hex representation */ param_type = DB_VALUE_DOMAIN_TYPE (param); +coerce_pos: if (TP_IS_CHAR_TYPE (param_type) || TP_IS_BIT_TYPE (param_type)) { if (TP_IS_CHAR_TYPE (param_type)) @@ -26776,14 +26778,34 @@ db_hex (const DB_VALUE * param, DB_VALUE * result) } else { - error_code = ER_QSTR_INVALID_DATA_TYPE; - goto error; + db_make_null (&tval); + ptval = &tval; + if (tp_value_cast (param, &tval, &tp_Char_domain, false) != DOMAIN_COMPATIBLE) + { + error_code = ER_QSTR_INVALID_DATA_TYPE; + goto error; + } + + param = &tval; + param_type = DB_VALUE_DOMAIN_TYPE (param); + assert (TP_IS_CHAR_TYPE (param_type)); + goto coerce_pos; + } + + if (ptval) + { + db_value_clear (ptval); } /* all ok */ return NO_ERROR; error: + if (ptval) + { + db_value_clear (ptval); + } + if (result) { db_make_null (result); diff --git a/src/query/xasl.h b/src/query/xasl.h index a5738aa709c..4a70a2471fe 100644 --- a/src/query/xasl.h +++ b/src/query/xasl.h @@ -30,13 +30,14 @@ #include "access_json_table.hpp" #include "access_spec.hpp" #include "memory_hash.h" -#include "method_def.hpp" + #include "query_hash_scan.h" #include "query_list.h" #include "regu_var.hpp" #include "storage_common.h" #include "string_opfunc.h" #include "subquery_cache.h" +#include "pl_signature.hpp" #if defined (SERVER_MODE) || defined (SA_MODE) #include "external_sort.h" @@ -891,7 +892,7 @@ struct method_spec_node XASL_NODE *xasl_node; /* the XASL node that contains the */ /* list file ID for the method */ /* arguments */ - METHOD_SIG_LIST *method_sig_list; /* method signature list */ + PL_SIGNATURE_ARRAY_TYPE *sig_array; /* method signature array */ }; struct dblink_spec_node @@ -984,8 +985,8 @@ union hybrid_node #define ACCESS_SPEC_METHOD_REGU_LIST(ptr) \ ((ptr)->s.method_node.method_regu_list) -#define ACCESS_SPEC_METHOD_SIG_LIST(ptr) \ - ((ptr)->s.method_node.method_sig_list) +#define ACCESS_SPEC_METHOD_SIG_ARRAY(ptr) \ + ((ptr)->s.method_node.sig_array) #define ACCESS_SPEC_METHOD_LIST_ID(ptr) \ (ACCESS_SPEC_METHOD_XASL_NODE(ptr)->list_id) diff --git a/src/query/xasl_to_stream.c b/src/query/xasl_to_stream.c index 56d23b4ed2f..bc335f24ad5 100644 --- a/src/query/xasl_to_stream.c +++ b/src/query/xasl_to_stream.c @@ -78,6 +78,7 @@ static int xts_save_aggregate_type (const AGGREGATE_TYPE * aggregate); static int xts_save_function_type (const FUNCTION_TYPE * function); static int xts_save_analytic_type (const ANALYTIC_TYPE * analytic); static int xts_save_analytic_eval_type (const ANALYTIC_EVAL_TYPE * analytic); +static int xts_save_sp_type (const SP_TYPE * sp); static int xts_save_srlist_id (const QFILE_SORTED_LIST_ID * sort_list_id); static int xts_save_list_id (const QFILE_LIST_ID * list_id); static int xts_save_arith_type (const ARITH_TYPE * arithmetic); @@ -121,12 +122,11 @@ static int xts_save_db_value_array (DB_VALUE ** ptr, int size); static int xts_save_int_array (int *ptr, int size); static int xts_save_hfid_array (HFID * ptr, int size); static int xts_save_oid_array (OID * ptr, int size); -static int xts_save_method_sig_list (const METHOD_SIG_LIST * ptr); -static int xts_save_method_sig (const METHOD_SIG * ptr, int size); static int xts_save_key_range_array (const KEY_RANGE * ptr, int size); static int xts_save_upddel_class_info_array (const UPDDEL_CLASS_INFO * classes, int nelements); static int xts_save_update_assignment_array (const UPDATE_ASSIGNMENT * assigns, int nelements); static int xts_save_odku_info (const ODKU_INFO * odku_info); +static int xts_save_packable_object (const cubpacking::packable_object & po); static char *xts_process (char *ptr, const json_table_column & json_table_col); static char *xts_process (char *ptr, const json_table_node & json_table_node); @@ -183,10 +183,9 @@ static char *xts_process_aggregate_type (char *ptr, const AGGREGATE_TYPE * aggre static char *xts_process_analytic_type (char *ptr, const ANALYTIC_TYPE * analytic); static char *xts_process_analytic_eval_type (char *ptr, const ANALYTIC_EVAL_TYPE * analytic); static char *xts_process_function_type (char *ptr, const FUNCTION_TYPE * function); +static char *xts_process_sp_type (char *ptr, const SP_TYPE * sp); static char *xts_process_srlist_id (char *ptr, const QFILE_SORTED_LIST_ID * sort_list_id); static char *xts_process_sort_list (char *ptr, const SORT_LIST * sort_list); -static char *xts_process_method_sig_list (char *ptr, const METHOD_SIG_LIST * method_sig_list); -static char *xts_process_method_sig (char *ptr, const METHOD_SIG * method_sig, int size); static char *xts_process_connectby_proc (char *ptr, const CONNECTBY_PROC_NODE * connectby_proc); static char *xts_process_regu_value_list (char *ptr, const REGU_VALUE_LIST * regu_value_list); static char *xts_process_sq_cache (char *ptr, const SQ_CACHE * sq_cache); @@ -245,11 +244,10 @@ static int xts_sizeof_analytic_type (const ANALYTIC_TYPE * ptr); static int xts_sizeof_analytic_eval_type (const ANALYTIC_EVAL_TYPE * ptr); static int xts_sizeof_srlist_id (const QFILE_SORTED_LIST_ID * ptr); static int xts_sizeof_sort_list (const SORT_LIST * ptr); -static int xts_sizeof_method_sig_list (const METHOD_SIG_LIST * ptr); -static int xts_sizeof_method_sig (const METHOD_SIG * ptr); static int xts_sizeof_connectby_proc (const CONNECTBY_PROC_NODE * ptr); static int xts_sizeof_regu_value_list (const REGU_VALUE_LIST * regu_value_list); static int xts_sizeof_cte_proc (const CTE_PROC_NODE * ptr); +static int xts_sizeof_sp_type (const SP_TYPE * sp); static int xts_mark_ptr_visited (const void *ptr, int offset); static int xts_get_offset_visited_ptr (const void *ptr); @@ -561,6 +559,74 @@ xts_save_aggregate_type (const AGGREGATE_TYPE * aggregate) return offset; } +static int +xts_save_sp_type (const SP_TYPE * sp) +{ + int offset; + int size; + OR_ALIGNED_BUF (sizeof (*sp) * 2) a_buf; + char *buf = OR_ALIGNED_BUF_START (a_buf); + char *buf_p = NULL; + bool is_buf_alloced = false; + + if (sp == NULL) + { + return NO_ERROR; + } + + offset = xts_get_offset_visited_ptr (sp); + if (offset != ER_FAILED) + { + return offset; + } + + size = xts_sizeof_sp_type (sp); + if (size == ER_FAILED) + { + return ER_FAILED; + } + + offset = xts_reserve_location_in_stream (size); + if (offset == ER_FAILED || xts_mark_ptr_visited (sp, offset) == ER_FAILED) + { + return ER_FAILED; + } + + if (size <= (int) OR_ALIGNED_BUF_SIZE (a_buf)) + { + buf_p = buf; + } + else + { + buf_p = (char *) malloc (size); + if (buf_p == NULL) + { + xts_Xasl_errcode = ER_OUT_OF_VIRTUAL_MEMORY; + return ER_FAILED; + } + + is_buf_alloced = true; + } + + buf = xts_process_sp_type (buf_p, sp); + if (buf == NULL) + { + offset = ER_FAILED; + goto end; + } + assert (buf <= buf_p + size); + + memcpy (&xts_Stream_buffer[offset], buf_p, size); + +end: + if (is_buf_alloced) + { + free_and_init (buf_p); + } + + return offset; +} + static int xts_save_function_type (const FUNCTION_TYPE * function) { @@ -2235,145 +2301,6 @@ xts_save_insert_info (const INSERT_PROC_NODE * insert_proc) } #endif -static int -xts_save_method_sig_list (const METHOD_SIG_LIST * method_sig_list) -{ - int offset; - int size; - OR_ALIGNED_BUF (sizeof (*method_sig_list) * 2) a_buf; - char *buf = OR_ALIGNED_BUF_START (a_buf); - char *buf_p = NULL; - bool is_buf_alloced = false; - - if (method_sig_list == NULL) - { - return NO_ERROR; - } - - offset = xts_get_offset_visited_ptr (method_sig_list); - if (offset != ER_FAILED) - { - return offset; - } - - size = xts_sizeof_method_sig_list (method_sig_list); - if (size == ER_FAILED) - { - return ER_FAILED; - } - - offset = xts_reserve_location_in_stream (size); - if (offset == ER_FAILED || xts_mark_ptr_visited (method_sig_list, offset) == ER_FAILED) - { - return ER_FAILED; - } - - if (size <= (int) OR_ALIGNED_BUF_SIZE (a_buf)) - { - buf_p = buf; - } - else - { - buf_p = (char *) malloc (size); - if (buf_p == NULL) - { - xts_Xasl_errcode = ER_OUT_OF_VIRTUAL_MEMORY; - return ER_FAILED; - } - - is_buf_alloced = true; - } - - buf = xts_process_method_sig_list (buf_p, method_sig_list); - if (buf == NULL) - { - offset = ER_FAILED; - goto end; - } - assert (buf <= buf_p + size); - - memcpy (&xts_Stream_buffer[offset], buf_p, size); - -end: - if (is_buf_alloced) - { - free_and_init (buf_p); - } - - return offset; -} - -static int -xts_save_method_sig (const METHOD_SIG * method_sig, int count) -{ - int offset; - int size; - OR_ALIGNED_BUF (sizeof (*method_sig) * 2) a_buf; - char *buf = OR_ALIGNED_BUF_START (a_buf); - char *buf_p = NULL; - bool is_buf_alloced = false; - - if (method_sig == NULL) - { - assert (count == 0); - return NO_ERROR; - } - - assert (count > 0); - - offset = xts_get_offset_visited_ptr (method_sig); - if (offset != ER_FAILED) - { - return offset; - } - - size = xts_sizeof_method_sig (method_sig); - if (size == ER_FAILED) - { - return ER_FAILED; - } - - offset = xts_reserve_location_in_stream (size); - if (offset == ER_FAILED || xts_mark_ptr_visited (method_sig, offset) == ER_FAILED) - { - return ER_FAILED; - } - - if (size <= (int) OR_ALIGNED_BUF_SIZE (a_buf)) - { - buf_p = buf; - } - else - { - buf_p = (char *) malloc (size); - if (buf_p == NULL) - { - xts_Xasl_errcode = ER_OUT_OF_VIRTUAL_MEMORY; - return ER_FAILED; - } - - is_buf_alloced = true; - } - - buf = xts_process_method_sig (buf_p, method_sig, count); - if (buf == NULL) - { - offset = ER_FAILED; - goto end; - } - assert (buf <= buf_p + size); - - memcpy (&xts_Stream_buffer[offset], buf_p, size); - -end: - if (is_buf_alloced) - { - free_and_init (buf_p); - } - - return offset; -} - static int xts_save_string (const char *string) { @@ -4047,6 +3974,37 @@ xts_save_update_assignment_array (const UPDATE_ASSIGNMENT * assigns, int nelemen return offset; } +static int +xts_save_packable_object (const cubpacking::packable_object & po) +{ + int offset, size, packed_length; + char *ptr; + + offset = xts_get_offset_visited_ptr (&po); + if (offset != ER_FAILED) + { + return offset; + } + + packing_packer packer; + cubmem::extensible_block eb; + packer.set_buffer_and_pack_all (eb, po); + + size = packer.get_current_size () + OR_INT_SIZE; + + offset = xts_reserve_location_in_stream (size); + if (offset == ER_FAILED || xts_mark_ptr_visited (&po, offset) == ER_FAILED) + { + return ER_FAILED; + } + + ptr = &xts_Stream_buffer[offset]; + ptr = or_pack_int (ptr, size); + memcpy (ptr, eb.get_ptr (), size); + + return offset; +} + static int xts_save_odku_info (const ODKU_INFO * odku_info) { @@ -5213,7 +5171,7 @@ xts_process_method_spec_type (char *ptr, const METHOD_SPEC_TYPE * method_spec) } ptr = or_pack_int (ptr, offset); - offset = xts_save_method_sig_list (method_spec->method_sig_list); + offset = xts_save_packable_object (*(method_spec->sig_array)); if (offset == ER_FAILED) { return NULL; @@ -5403,6 +5361,15 @@ xts_pack_regu_variable_value (char *ptr, const REGU_VARIABLE * regu_var) ptr = or_pack_int (ptr, offset); break; + case TYPE_SP: + offset = xts_save_sp_type (regu_var->value.sp_ptr); + if (offset == ER_FAILED) + { + return NULL; + } + ptr = or_pack_int (ptr, offset); + break; + case TYPE_FUNC: offset = xts_save_function_type (regu_var->value.funcp); if (offset == ER_FAILED) @@ -5745,25 +5712,25 @@ xts_process_analytic_type (char *ptr, const ANALYTIC_TYPE * analytic) } static char * -xts_process_analytic_eval_type (char *ptr, const ANALYTIC_EVAL_TYPE * analytic_eval) +xts_process_sp_type (char *ptr, const SP_TYPE * sp) { int offset; - offset = xts_save_analytic_type (analytic_eval->head); + offset = xts_save_db_value (sp->value); if (offset == ER_FAILED) { return NULL; } ptr = or_pack_int (ptr, offset); - offset = xts_save_sort_list (analytic_eval->sort_list); + offset = xts_save_regu_variable_list (sp->args); if (offset == ER_FAILED) { return NULL; } ptr = or_pack_int (ptr, offset); - offset = xts_save_analytic_eval_type (analytic_eval->next); + offset = xts_save_packable_object (*sp->sig); if (offset == ER_FAILED) { return NULL; @@ -5774,74 +5741,42 @@ xts_process_analytic_eval_type (char *ptr, const ANALYTIC_EVAL_TYPE * analytic_e } static char * -xts_process_srlist_id (char *ptr, const QFILE_SORTED_LIST_ID * sort_list_id) +xts_process_analytic_eval_type (char *ptr, const ANALYTIC_EVAL_TYPE * analytic_eval) { int offset; - ptr = or_pack_int (ptr, sort_list_id->sorted); - - offset = xts_save_list_id (sort_list_id->list_id); + offset = xts_save_analytic_type (analytic_eval->head); if (offset == ER_FAILED) { return NULL; } ptr = or_pack_int (ptr, offset); - return ptr; -} - -static char * -xts_process_sort_list (char *ptr, const SORT_LIST * sort_list) -{ - int offset; - - offset = xts_save_sort_list (sort_list->next); + offset = xts_save_sort_list (analytic_eval->sort_list); if (offset == ER_FAILED) { return NULL; } ptr = or_pack_int (ptr, offset); - ptr = xts_process_pos_descr (ptr, &sort_list->pos_descr); - if (ptr == NULL) + offset = xts_save_analytic_eval_type (analytic_eval->next); + if (offset == ER_FAILED) { return NULL; } - - ptr = or_pack_int (ptr, sort_list->s_order); - ptr = or_pack_int (ptr, sort_list->s_nulls); - - /* others (not sent to server) */ + ptr = or_pack_int (ptr, offset); return ptr; } -/* - * xts_process_method_sig_list ( ) - - * - * Note: do not use or_pack_method_sig_list - */ static char * -xts_process_method_sig_list (char *ptr, const METHOD_SIG_LIST * method_sig_list) +xts_process_srlist_id (char *ptr, const QFILE_SORTED_LIST_ID * sort_list_id) { int offset; -#if !defined(NDEBUG) - { - int i = 0; - METHOD_SIG *sig; - - for (sig = method_sig_list->method_sig; sig; sig = sig->next) - { - i++; - } - assert (method_sig_list->num_methods == i); - } -#endif - - ptr = or_pack_int (ptr, method_sig_list->num_methods); + ptr = or_pack_int (ptr, sort_list_id->sorted); - offset = xts_save_method_sig (method_sig_list->method_sig, method_sig_list->num_methods); + offset = xts_save_list_id (sort_list_id->list_id); if (offset == ER_FAILED) { return NULL; @@ -5852,57 +5787,27 @@ xts_process_method_sig_list (char *ptr, const METHOD_SIG_LIST * method_sig_list) } static char * -xts_process_method_sig (char *ptr, const METHOD_SIG * method_sig, int count) +xts_process_sort_list (char *ptr, const SORT_LIST * sort_list) { int offset; - int n; - - assert (method_sig->method_name != NULL); - offset = xts_save_string (method_sig->method_name); + offset = xts_save_sort_list (sort_list->next); if (offset == ER_FAILED) { return NULL; } ptr = or_pack_int (ptr, offset); - ptr = or_pack_int (ptr, method_sig->method_type); - ptr = or_pack_int (ptr, method_sig->num_method_args); - - for (n = 0; n < method_sig->num_method_args + 1; n++) + ptr = xts_process_pos_descr (ptr, &sort_list->pos_descr); + if (ptr == NULL) { - ptr = or_pack_int (ptr, method_sig->method_arg_pos[n]); + return NULL; } - if (method_sig->method_type == METHOD_TYPE_JAVA_SP) - { - for (n = 0; n < method_sig->num_method_args; n++) - { - ptr = or_pack_int (ptr, method_sig->arg_info.arg_mode[n]); - } - for (n = 0; n < method_sig->num_method_args; n++) - { - ptr = or_pack_int (ptr, method_sig->arg_info.arg_type[n]); - } - - ptr = or_pack_int (ptr, method_sig->arg_info.result_type); - } - else - { - offset = xts_save_string (method_sig->class_name); /* is can be null */ - if (offset == ER_FAILED) - { - return NULL; - } - ptr = or_pack_int (ptr, offset); - } + ptr = or_pack_int (ptr, sort_list->s_order); + ptr = or_pack_int (ptr, sort_list->s_nulls); - offset = xts_save_method_sig (method_sig->next, count - 1); - if (offset == ER_FAILED) - { - return NULL; - } - ptr = or_pack_int (ptr, offset); + /* others (not sent to server) */ return ptr; } @@ -7167,7 +7072,7 @@ xts_sizeof_method_spec_type (const METHOD_SPEC_TYPE * method_spec) size += (PTR_SIZE /* method_regu_list */ + PTR_SIZE /* xasl_node */ - + PTR_SIZE); /* method_sig_list */ + + PTR_SIZE); /* sig_array */ return size; } @@ -7387,6 +7292,10 @@ xts_get_regu_variable_value_size (const REGU_VARIABLE * regu_var) size = PTR_SIZE; /* arithptr */ break; + case TYPE_SP: + size = PTR_SIZE; /* sp_ptr */ + break; + case TYPE_FUNC: size = PTR_SIZE; /* funcp */ break; @@ -7543,6 +7452,23 @@ xts_sizeof_aggregate_type (const AGGREGATE_TYPE * aggregate) return size; } +/* + * xts_sizeof_function_type () - + * return: + * ptr(in) : + */ +static int +xts_sizeof_sp_type (const SP_TYPE * sp) +{ + int size = 0; + + size += (PTR_SIZE /* value */ + + PTR_SIZE /* sig */ + + PTR_SIZE); /* args */ + + return size; +} + /* * xts_sizeof_function_type () - * return: @@ -7674,47 +7600,6 @@ xts_sizeof_sort_list (const SORT_LIST * sort_lis) return size; } -/* - * xts_sizeof_method_sig_list () - - * return: - * ptr(in) : - */ -static int -xts_sizeof_method_sig_list (const METHOD_SIG_LIST * method_sig_list) -{ - int size = 0; - - size += (OR_INT_SIZE /* num_methods */ - + PTR_SIZE); /* method_sig */ - - return size; -} - -static int -xts_sizeof_method_sig (const METHOD_SIG * method_sig) -{ - int size = 0; - - size += (PTR_SIZE /* method_name */ - + OR_INT_SIZE /* method_type */ - + OR_INT_SIZE /* num_method_args */ - + (OR_INT_SIZE * (method_sig->num_method_args + 1)) /* method_arg_pos */ - + PTR_SIZE); /* next */ - - if (method_sig->method_type == METHOD_TYPE_JAVA_SP) - { - size += ((method_sig->num_method_args * OR_INT_SIZE) /* arg_mode */ - + (method_sig->num_method_args * OR_INT_SIZE) /* arg_type */ - + (OR_INT_SIZE)); /* result type */ - } - else - { - size += PTR_SIZE; /* class_name */ - } - - return size; -} - /* * xts_sizeof_connectby_proc () - * return: diff --git a/src/session/session.c b/src/session/session.c index 6d1f54234fe..fab62a4997f 100644 --- a/src/session/session.c +++ b/src/session/session.c @@ -53,6 +53,8 @@ #include "thread_lockfree_hash_map.hpp" #include "thread_manager.hpp" #include "xasl_cache.h" +#include "pl_session.hpp" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" @@ -135,7 +137,7 @@ struct session_state int private_lru_index; load_session *load_session_p; - method_runtime_context *method_rctx_p; + PL_SESSION *pl_session_p; // *INDENT-OFF* session_state (); @@ -314,7 +316,7 @@ session_state_init (void *st) session_p->private_lru_index = -1; session_p->auto_commit = false; session_p->load_session_p = NULL; - session_p->method_rctx_p = NULL; + session_p->pl_session_p = NULL; return NO_ERROR; } @@ -3182,8 +3184,7 @@ session_get_load_session (THREAD_ENTRY * thread_p, REFPTR (load_session, load_se } int -session_get_method_runtime_context (THREAD_ENTRY * thread_p, - REFPTR (method_runtime_context, method_runtime_context_ref_ptr)) +session_get_pl_session (THREAD_ENTRY * thread_p, REFPTR (PL_SESSION, pl_session_ref_ptr)) { SESSION_STATE *state_p = NULL; @@ -3193,12 +3194,12 @@ session_get_method_runtime_context (THREAD_ENTRY * thread_p, return ER_FAILED; } - if (state_p->method_rctx_p == NULL) + if (state_p->pl_session_p == NULL) { - state_p->method_rctx_p = new method_runtime_context (); + state_p->pl_session_p = new PL_SESSION (); } - method_runtime_context_ref_ptr = state_p->method_rctx_p; + pl_session_ref_ptr = state_p->pl_session_p; return NO_ERROR; } @@ -3226,13 +3227,13 @@ session_stop_attached_threads (void *session_arg) session->load_session_p = NULL; } - if (session->method_rctx_p != NULL) + if (session->pl_session_p != NULL) { - session->method_rctx_p->set_interrupt (er_errid ()); - session->method_rctx_p->wait_for_interrupt (); + session->pl_session_p->set_interrupt (er_errid ()); + session->pl_session_p->wait_for_interrupt (); - delete session->method_rctx_p; - session->method_rctx_p = NULL; + delete session->pl_session_p; + session->pl_session_p = NULL; } #endif } diff --git a/src/session/session.h b/src/session/session.h index c5da4146b51..6b55c12afea 100644 --- a/src/session/session.h +++ b/src/session/session.h @@ -33,7 +33,7 @@ #include "system_parameter.h" #include "thread_compat.hpp" #include "tz_support.h" -#include "method_runtime_context.hpp" +#include "pl_session.hpp" // forward definitions struct xasl_cache_ent; @@ -89,7 +89,6 @@ extern int session_set_tran_auto_commit (THREAD_ENTRY * thread_p, bool auto_comm extern int session_set_load_session (THREAD_ENTRY * thread_p, load_session * load_session_p); extern int session_get_load_session (THREAD_ENTRY * thread_p, REFPTR (load_session, load_session_ref_ptr)); -extern int session_get_method_runtime_context (THREAD_ENTRY * thread_p, - REFPTR (method_runtime_context, method_runtime_context_ref_ptr)); +extern int session_get_pl_session (THREAD_ENTRY * thread_p, REFPTR (PL_SESSION, pl_session_ref_ptr)); extern void session_stop_attached_threads (void *session); #endif /* _SESSION_H_ */ diff --git a/src/sp/Makefile_jspserver b/src/sp/Makefile_jspserver deleted file mode 100644 index b00bc093918..00000000000 --- a/src/sp/Makefile_jspserver +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2008 Search Solution Corporation -# Copyright 2016 CUBRID Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# - -JDBC_SRC_DIR = . - -BIN_DIR = bin -SRC_DIR = src - -JDBC_BUILD_NUMBER := $(shell cat ../../BUILD_NUMBER) - -JDBC_DRIVER = jspserver.jar - -all: $(JDBC_DRIVER) - -clean: - ant -buildfile ../../java/build.xml -Dbasedir=. -Dversion=$(JDBC_BUILD_NUMBER) clean - -$(JDBC_DRIVER): - ant -buildfile ../../java/build.xml -Dbasedir=. -Dsrc=$(JDBC_SRC_DIR) -Dversion=$(JDBC_BUILD_NUMBER) dist diff --git a/src/sp/jsp_cl.c b/src/sp/jsp_cl.c deleted file mode 100644 index 5bf60d2c00a..00000000000 --- a/src/sp/jsp_cl.c +++ /dev/null @@ -1,1647 +0,0 @@ -/* - * Copyright 2008 Search Solution Corporation - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * jsp_cl.c - Java Stored Procedure Client Module Source - */ - -#ident "$Id$" - -#include "config.h" - -#include -#if !defined(WINDOWS) -#include -#else /* not WINDOWS */ -#include -#endif /* not WINDOWS */ - -#include -#include - -#include "authenticate.h" -#include "error_manager.h" -#include "memory_alloc.h" -#include "dbtype.h" -#include "parser.h" -#include "object_domain.h" -#include "object_primitive.h" -#include "object_representation.h" -#include "db.h" -#include "object_accessor.h" -#include "set_object.h" -#include "locator_cl.h" -#include "transaction_cl.h" -#include "schema_manager.h" -#include "numeric_opfunc.h" -#include "jsp_cl.h" -#include "system_parameter.h" -#include "network_interface_cl.h" -#include "unicode_support.h" -#include "dbtype.h" -#include "jsp_comm.h" -#include "method_compile_def.hpp" -#include "parser_message.h" - -#define PT_NODE_SP_NAME(node) \ - ((node)->info.sp.name->info.name.original) - -#define PT_NODE_SP_TYPE(node) \ - ((node)->info.sp.type) - -#define PT_NODE_SP_RETURN_TYPE(node) \ - ((node)->info.sp.ret_type->info.name.original) - -#define PT_NODE_SP_BODY(node) \ - ((node)->info.sp.body) - -#define PT_NODE_SP_LANG(node) \ - ((node)->info.sp.body->info.sp_body.lang) - -#define PT_NODE_SP_DIRECT(node) \ - ((node)->info.sp.body->info.sp_body.direct) - -#define PT_NODE_SP_IMPL(node) \ - ((node)->info.sp.body->info.sp_body.impl->info.value.data_value.str->bytes) - -#define PT_NODE_SP_JAVA_METHOD(node) \ - ((node)->info.sp.body->info.sp_body.decl->info.value.data_value.str->bytes) - -#define PT_NODE_SP_COMMENT(node) \ - (((node)->info.sp.comment == NULL) ? NULL : \ - (node)->info.sp.comment->info.value.data_value.str->bytes) - -#define PT_NODE_SP_ARG_COMMENT(node) \ - (((node)->info.sp_param.comment == NULL) ? NULL : \ - (node)->info.sp_param.comment->info.value.data_value.str->bytes) - -#define MAX_CALL_COUNT 16 -#define SAVEPOINT_ADD_STORED_PROC "ADDSTOREDPROC" -#define SAVEPOINT_CREATE_STORED_PROC "CREATESTOREDPROC" - -#define MAX_ARG_COUNT 64 - -static int server_port = -1; -static int call_cnt = 0; -static bool is_prepare_call[MAX_CALL_COUNT] = { false, }; - -static SP_TYPE_ENUM jsp_map_pt_misc_to_sp_type (PT_MISC_TYPE pt_enum); -static int jsp_map_pt_misc_to_sp_mode (PT_MISC_TYPE pt_enum); -static PT_MISC_TYPE jsp_map_sp_type_to_pt_misc (SP_TYPE_ENUM sp_type); - -static int jsp_add_stored_procedure_argument (MOP * mop_p, const char *sp_name, const char *arg_name, int index, - PT_TYPE_ENUM data_type, PT_MISC_TYPE mode, const char *arg_comment); -static char *jsp_check_stored_procedure_name (const char *str); -static int jsp_add_stored_procedure (const char *name, const PT_MISC_TYPE type, const PT_TYPE_ENUM ret_type, - PT_NODE * param_list, const char *java_method, const char *comment); -static int drop_stored_procedure (const char *name, PT_MISC_TYPE expected_type); - -static int jsp_make_method_sig_list (PARSER_CONTEXT * parser, PT_NODE * node_list, method_sig_list & sig_list); -static int *jsp_make_method_arglist (PARSER_CONTEXT * parser, PT_NODE * node_list); - -extern bool ssl_client; - -/* - * jsp_find_stored_procedure - * return: MOP - * name(in): find java stored procedure name - * - * Note: - */ - -MOP -jsp_find_stored_procedure (const char *name) -{ - MOP mop = NULL; - DB_VALUE value; - int save; - char *checked_name; - - if (!name) - { - return NULL; - } - - AU_DISABLE (save); - - checked_name = jsp_check_stored_procedure_name (name); - db_make_string (&value, checked_name); - mop = db_find_unique (db_find_class (SP_CLASS_NAME), SP_ATTR_NAME, &value); - - if (er_errid () == ER_OBJ_OBJECT_NOT_FOUND) - { - er_clear (); - er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_EXIST, 1, name); - } - - free_and_init (checked_name); - AU_ENABLE (save); - - return mop; -} - -/* - * jsp_is_exist_stored_procedure - * return: name is exist then return true - * else return false - * name(in): find java stored procedure name - * - * Note: - */ - -int -jsp_is_exist_stored_procedure (const char *name) -{ - MOP mop = NULL; - - mop = jsp_find_stored_procedure (name); - er_clear (); - - return mop != NULL; -} - -int -jsp_check_out_param_in_query (PARSER_CONTEXT * parser, PT_NODE * node, int arg_mode) -{ - int error = NO_ERROR; - - assert ((node) && (node)->node_type == PT_METHOD_CALL); - - if (node->info.method_call.call_or_expr != PT_IS_CALL_STMT) - { - // check out parameters - if (arg_mode != SP_MODE_IN) - { - PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_SP_OUT_ARGS_EXISTS_IN_QUERY, - node->info.method_call.method_name->info.name.original); - error = ER_PT_SEMANTIC; - } - } - - return error; -} - -/* - * jsp_check_param_type_supported - * - * Note: - */ - -int -jsp_check_param_type_supported (PT_NODE * node) -{ - assert (node && node->node_type == PT_SP_PARAMETERS); - - PT_TYPE_ENUM pt_type = node->type_enum; - DB_TYPE domain_type = pt_type_enum_to_db (pt_type); - - switch (domain_type) - { - case DB_TYPE_INTEGER: - case DB_TYPE_FLOAT: - case DB_TYPE_DOUBLE: - case DB_TYPE_STRING: - case DB_TYPE_OBJECT: - case DB_TYPE_SET: - case DB_TYPE_MULTISET: - case DB_TYPE_SEQUENCE: - case DB_TYPE_TIME: - case DB_TYPE_TIMESTAMP: - case DB_TYPE_DATE: - case DB_TYPE_MONETARY: - case DB_TYPE_SHORT: - case DB_TYPE_NUMERIC: - case DB_TYPE_CHAR: - case DB_TYPE_BIGINT: - case DB_TYPE_DATETIME: - return NO_ERROR; - break; - - case DB_TYPE_RESULTSET: - if (node->info.sp_param.mode != PT_OUTPUT) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_INPUT_RESULTSET, 0); - } - break; - - default: - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_SUPPORTED_ARG_TYPE, 1, pr_type_name (domain_type)); - break; - } - - return er_errid (); -} - - -/* - * jsp_check_return_type_supported - * - * Note: - */ - -int -jsp_check_return_type_supported (DB_TYPE type) -{ - switch (type) - { - case DB_TYPE_NULL: - case DB_TYPE_INTEGER: - case DB_TYPE_FLOAT: - case DB_TYPE_DOUBLE: - case DB_TYPE_STRING: - case DB_TYPE_OBJECT: - case DB_TYPE_SET: - case DB_TYPE_MULTISET: - case DB_TYPE_SEQUENCE: - case DB_TYPE_TIME: - case DB_TYPE_TIMESTAMP: - case DB_TYPE_DATE: - case DB_TYPE_MONETARY: - case DB_TYPE_SHORT: - case DB_TYPE_NUMERIC: - case DB_TYPE_CHAR: - case DB_TYPE_BIGINT: - case DB_TYPE_DATETIME: - case DB_TYPE_RESULTSET: - return NO_ERROR; - break; - - default: - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_SUPPORTED_RETURN_TYPE, 1, pr_type_name (type)); - break; - } - - return er_errid (); -} - -/* - * jsp_get_return_type - Return Java Stored Procedure Type - * return: if fail return error code - * else return Java Stored Procedure Type - * name(in): java stored procedure name - * - * Note: - */ - -int -jsp_get_return_type (const char *name) -{ - DB_OBJECT *mop_p; - DB_VALUE return_type; - int err; - int save; - - AU_DISABLE (save); - - mop_p = jsp_find_stored_procedure (name); - if (mop_p == NULL) - { - AU_ENABLE (save); - - assert (er_errid () != NO_ERROR); - return er_errid (); - } - - err = db_get (mop_p, SP_ATTR_RETURN_TYPE, &return_type); - if (err != NO_ERROR) - { - AU_ENABLE (save); - return err; - } - - AU_ENABLE (save); - return db_get_int (&return_type); -} - -/* - * jsp_get_sp_type - Return Java Stored Procedure Type - * return: if fail return error code - * else return Java Stored Procedure Type - * name(in): java stored procedure name - * - * Note: - */ - -int -jsp_get_sp_type (const char *name) -{ - DB_OBJECT *mop_p; - DB_VALUE sp_type_val; - int err; - int save; - - AU_DISABLE (save); - - mop_p = jsp_find_stored_procedure (name); - if (mop_p == NULL) - { - AU_ENABLE (save); - - assert (er_errid () != NO_ERROR); - return er_errid (); - } - - /* check type */ - err = db_get (mop_p, SP_ATTR_SP_TYPE, &sp_type_val); - if (err != NO_ERROR) - { - AU_ENABLE (save); - return err; - } - - AU_ENABLE (save); - return jsp_map_sp_type_to_pt_misc ((SP_TYPE_ENUM) db_get_int (&sp_type_val)); -} - -static PT_MISC_TYPE -jsp_map_sp_type_to_pt_misc (SP_TYPE_ENUM sp_type) -{ - if (sp_type == SP_TYPE_PROCEDURE) - { - return PT_SP_PROCEDURE; - } - else - { - return PT_SP_FUNCTION; - } -} - -/* - * jsp_call_stored_procedure - call java stored procedure in constant folding - * return: call jsp failed return error code - * parser(in/out): parser environment - * statement(in): a statement node - * - * Note: - */ - -int -jsp_call_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * statement) -{ - int error = NO_ERROR; - PT_NODE *method; - const char *method_name; - if (!statement || !(method = statement->info.method_call.method_name) || method->node_type != PT_NAME - || !(method_name = method->info.name.original)) - { - er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ARGUMENTS, 0); - return er_errid (); - } - - DB_VALUE ret_value; - db_make_null (&ret_value); - - // *INDENT-OFF* - std::vector > args; - // *INDENT-ON* - - PT_NODE *vc = statement->info.method_call.arg_list; - while (vc) - { - DB_VALUE *db_value; - bool to_break = false; - - /* - * Don't clone host vars; they may actually be acting as output variables (e.g., a character array that is - * intended to receive bytes from the method), and cloning will ensure that the results never make it to the - * expected area. Since pt_evaluate_tree() always clones its db_values we must not use pt_evaluate_tree() to - * extract the db_value from a host variable; instead extract it ourselves. */ - if (PT_IS_CONST (vc)) - { - db_value = pt_value_to_db (parser, vc); - } - else - { - db_value = (DB_VALUE *) malloc (sizeof (DB_VALUE)); - if (db_value == NULL) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (DB_VALUE)); - return er_errid (); - } - - /* must call pt_evaluate_tree */ - pt_evaluate_tree (parser, vc, db_value, 1); - if (pt_has_error (parser)) - { - /* to maintain the list to free all the allocated */ - to_break = true; - } - } - - args.push_back (std::ref (*db_value)); - vc = vc->next; - - if (to_break) - { - break; - } - } - - if (pt_has_error (parser)) - { - pt_report_to_ersys (parser, PT_SEMANTIC); - error = er_errid (); - } - else - { - /* call sp */ - method_sig_list sig_list; - - sig_list.method_sig = nullptr; - sig_list.num_methods = 0; - - error = jsp_make_method_sig_list (parser, statement, sig_list); - if (error == NO_ERROR && locator_get_sig_interrupt () == 0) - { - error = method_invoke_fold_constants (sig_list, args, ret_value); - } - sig_list.freemem (); - } - - if (error == NO_ERROR) - { - vc = statement->info.method_call.arg_list; - for (int i = 0; i < (int) args.size () && vc; i++) - { - if (!PT_IS_CONST (vc)) - { - DB_VALUE & arg = args[i]; - db_value_clear (&arg); - free (&arg); - } - vc = vc->next; - } - } - - if (error == NO_ERROR) - { - /* Save the method result and its domain */ - statement->etc = (void *) db_value_copy (&ret_value); - statement = pt_bind_type_from_dbval (parser, statement, &ret_value); - - PT_NODE *into = statement->info.method_call.to_return_var; - - const char *into_label; - if (into != NULL && into->node_type == PT_NAME && (into_label = into->info.name.original) != NULL) - { - /* create another DB_VALUE of the new instance for the label_table */ - DB_VALUE *ins_value = db_value_copy (&ret_value); - error = pt_associate_label_with_value_check_reference (into_label, ins_value); - } - } - -#if defined (CS_MODE) - db_value_clear (&ret_value); -#endif - - return error; -} - -/* - * jsp_drop_stored_procedure - drop java stored procedure - * return: Error code - * parser(in/out): parser environment - * statement(in): a statement node - * - * Note: - */ - -int -jsp_drop_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * statement) -{ - const char *name; - PT_MISC_TYPE type; - PT_NODE *name_list, *p; - int i; - int err = NO_ERROR; - - CHECK_MODIFICATION_ERROR (); - - if (prm_get_bool_value (PRM_ID_BLOCK_DDL_STATEMENT)) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_BLOCK_DDL_STMT, 0); - return ER_BLOCK_DDL_STMT; - } - - name_list = statement->info.sp.name; - type = PT_NODE_SP_TYPE (statement); - - for (p = name_list, i = 0; p != NULL; p = p->next) - { - name = (char *) p->info.name.original; - if (name == NULL || name[0] == '\0') - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_NAME, 0); - return er_errid (); - } - - err = drop_stored_procedure (name, type); - if (err != NO_ERROR) - { - break; - } - } - - return err; -} - -/* - * jsp_create_stored_procedure - * return: if failed return error code else execute jsp_add_stored_procedure - * function - * parser(in/out): parser environment - * statement(in): a statement node - * - * Note: - */ - -int -jsp_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * statement) -{ - const char *name, *decl, *comment = NULL; - - PT_MISC_TYPE type; - PT_NODE *param_list, *p; - PT_TYPE_ENUM ret_type = PT_TYPE_NONE; - int param_count; - int lang; - int err = NO_ERROR; - bool has_savepoint = false; - PLCSQL_COMPILE_INFO compile_info; - - CHECK_MODIFICATION_ERROR (); - - if (prm_get_bool_value (PRM_ID_BLOCK_DDL_STATEMENT)) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_BLOCK_DDL_STMT, 0); - return ER_BLOCK_DDL_STMT; - } - - name = (char *) PT_NODE_SP_NAME (statement); - if (name == NULL || name[0] == '\0') - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_NAME, 0); - return er_errid (); - } - - type = PT_NODE_SP_TYPE (statement); - if (type == PT_SP_FUNCTION) - { - ret_type = statement->info.sp.ret_type; - } - - param_list = statement->info.sp.param_list; - for (p = param_list, param_count = 0; p != NULL; p = p->next, param_count++) - { - ; - } - - if (param_count > MAX_ARG_COUNT) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_TOO_MANY_ARG_COUNT, 1, name); - goto error_exit; - } - - lang = PT_NODE_SP_LANG (statement); - if (lang == SP_LANG_PLCSQL) - { - std::string pl_code (statement->sql_user_text, statement->sql_user_text_len); - err = plcsql_transfer_file (pl_code, false, compile_info); - if (err == NO_ERROR && compile_info.err_code == NO_ERROR) - { - decl = compile_info.java_signature.c_str (); - } - else - { - // TODO: error handling needs to be improved - err = ER_SP_COMPILE_ERROR; - - std::string err_msg; - if (compile_info.err_msg.empty ()) - { - err_msg = "unknown"; - } - else - { - err_msg.assign (compile_info.err_msg); - } - - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_COMPILE_ERROR, 3, compile_info.err_line, - compile_info.err_column, err_msg.c_str ()); - pt_record_error (parser, parser->statement_number, compile_info.err_line, compile_info.err_column, er_msg (), - NULL); - } - } - else /* SP_LANG_JAVA */ - { - bool is_direct = PT_NODE_SP_DIRECT (statement); - if (is_direct) - { - // TODO: CBRD-24641 - assert (false); - } - else - { - decl = (const char *) PT_NODE_SP_JAVA_METHOD (statement); - } - } - - if (err != NO_ERROR) - { - goto error_exit; - } - - /* check already exists */ - if (jsp_is_exist_stored_procedure (name)) - { - if (statement->info.sp.or_replace) - { - /* drop existing stored procedure */ - err = tran_system_savepoint (SAVEPOINT_CREATE_STORED_PROC); - if (err != NO_ERROR) - { - return err; - } - has_savepoint = true; - - err = drop_stored_procedure (name, type); - if (err != NO_ERROR) - { - goto error_exit; - } - } - else - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_ALREADY_EXIST, 1, name); - return er_errid (); - } - } - - comment = (char *) PT_NODE_SP_COMMENT (statement); - - err = jsp_add_stored_procedure (name, type, ret_type, param_list, decl, comment); - if (err != NO_ERROR) - { - goto error_exit; - } - return NO_ERROR; - -error_exit: - if (has_savepoint) - { - tran_abort_upto_system_savepoint (SAVEPOINT_CREATE_STORED_PROC); - } - return (er_errid () != NO_ERROR) ? er_errid () : ER_FAILED; -} - -/* - * jsp_alter_stored_procedure - * return: if failed return error code else NO_ERROR - * parser(in/out): parser environment - * statement(in): a statement node - * - * Note: - */ - -int -jsp_alter_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * statement) -{ - int err = NO_ERROR; - PT_NODE *sp_name = NULL, *sp_owner = NULL, *sp_comment = NULL; - const char *name_str = NULL, *owner_str = NULL, *comment_str = NULL; - PT_MISC_TYPE type; - SP_TYPE_ENUM real_type; - MOP sp_mop = NULL, new_owner = NULL; - DB_VALUE user_val, sp_type_val; - int save; - - assert (statement != NULL); - - CHECK_MODIFICATION_ERROR (); - - if (prm_get_bool_value (PRM_ID_BLOCK_DDL_STATEMENT)) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_BLOCK_DDL_STMT, 0); - return ER_BLOCK_DDL_STMT; - } - - db_make_null (&user_val); - - type = PT_NODE_SP_TYPE (statement); - sp_name = statement->info.sp.name; - assert (sp_name != NULL); - - sp_owner = statement->info.sp.owner; - sp_comment = statement->info.sp.comment; - assert (sp_owner != NULL || sp_comment != NULL); - - name_str = sp_name->info.name.original; - assert (name_str != NULL); - - if (sp_owner != NULL) - { - owner_str = sp_owner->info.name.original; - assert (owner_str != NULL); - } - - comment_str = (char *) PT_NODE_SP_COMMENT (statement); - - AU_DISABLE (save); - - /* authentication */ - if (!au_is_dba_group_member (Au_user)) - { - err = ER_AU_DBA_ONLY; - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, err, 1, "change stored procedure owner"); - goto error; - } - - /* existence of sp */ - sp_mop = jsp_find_stored_procedure (name_str); - if (sp_mop == NULL) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - goto error; - } - - /* existence of new owner */ - if (sp_owner != NULL) - { - new_owner = db_find_user (owner_str); - if (new_owner == NULL) - { - err = ER_OBJ_OBJECT_NOT_FOUND; - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, err, 1, owner_str); - goto error; - } - } - - /* check type */ - err = db_get (sp_mop, SP_ATTR_SP_TYPE, &sp_type_val); - if (err != NO_ERROR) - { - goto error; - } - - real_type = (SP_TYPE_ENUM) db_get_int (&sp_type_val); - if (real_type != jsp_map_pt_misc_to_sp_type (type)) - { - err = ER_SP_INVALID_TYPE; - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, err, 2, name_str, - real_type == SP_TYPE_FUNCTION ? "FUNCTION" : "PROCEDURE"); - goto error; - } - - /* change the owner */ - if (sp_owner != NULL) - { - db_make_object (&user_val, new_owner); - err = obj_set (sp_mop, SP_ATTR_OWNER, &user_val); - if (err < 0) - { - goto error; - } - pr_clear_value (&user_val); - } - - /* change the comment */ - if (sp_comment != NULL) - { - db_make_string (&user_val, comment_str); - err = obj_set (sp_mop, SP_ATTR_COMMENT, &user_val); - if (err < 0) - { - goto error; - } - pr_clear_value (&user_val); - } - -error: - - pr_clear_value (&user_val); - AU_ENABLE (save); - - return err; -} - -/* - * jsp_map_pt_misc_to_sp_type - * return : stored procedure type ( Procedure or Function ) - * pt_enum(in): Misc Types - * - * Note: - */ - -static SP_TYPE_ENUM -jsp_map_pt_misc_to_sp_type (PT_MISC_TYPE pt_enum) -{ - if (pt_enum == PT_SP_PROCEDURE) - { - return SP_TYPE_PROCEDURE; - } - else - { - return SP_TYPE_FUNCTION; - } -} - -/* - * jsp_map_pt_misc_to_sp_mode - * return : stored procedure mode ( input or output or inout ) - * pt_enum(in) : Misc Types - * - * Note: - */ - -static int -jsp_map_pt_misc_to_sp_mode (PT_MISC_TYPE pt_enum) -{ - if (pt_enum == PT_INPUT || pt_enum == PT_NOPUT) - { - return SP_MODE_IN; - } - else if (pt_enum == PT_OUTPUT) - { - return SP_MODE_OUT; - } - else - { - return SP_MODE_INOUT; - } -} - -/* - * jsp_add_stored_procedure_argument - * return: Error Code - * mop_p(in/out) : - * sp_name(in) : - * arg_name(in) : - * index(in) : - * data_type(in) : - * mode(in) : - * arg_comment(in): - * - * Note: - */ - -static int -jsp_add_stored_procedure_argument (MOP * mop_p, const char *sp_name, const char *arg_name, int index, - PT_TYPE_ENUM data_type, PT_MISC_TYPE mode, const char *arg_comment) -{ - DB_OBJECT *classobj_p, *object_p; - DB_OTMPL *obt_p = NULL; - DB_VALUE value; - int save; - int err; - - AU_DISABLE (save); - - classobj_p = db_find_class (SP_ARG_CLASS_NAME); - if (classobj_p == NULL) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - goto error; - } - - obt_p = dbt_create_object_internal (classobj_p); - if (obt_p == NULL) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - goto error; - } - - db_make_string (&value, sp_name); - err = dbt_put_internal (obt_p, SP_ATTR_NAME, &value); - pr_clear_value (&value); - if (err != NO_ERROR) - { - goto error; - } - - db_make_string (&value, arg_name); - err = dbt_put_internal (obt_p, SP_ATTR_ARG_NAME, &value); - pr_clear_value (&value); - if (err != NO_ERROR) - { - goto error; - } - - db_make_int (&value, index); - err = dbt_put_internal (obt_p, SP_ATTR_INDEX_OF_NAME, &value); - if (err != NO_ERROR) - { - goto error; - } - - db_make_int (&value, pt_type_enum_to_db (data_type)); - err = dbt_put_internal (obt_p, SP_ATTR_DATA_TYPE, &value); - if (err != NO_ERROR) - { - goto error; - } - - db_make_int (&value, jsp_map_pt_misc_to_sp_mode (mode)); - err = dbt_put_internal (obt_p, SP_ATTR_MODE, &value); - if (err != NO_ERROR) - { - goto error; - } - - db_make_string (&value, arg_comment); - err = dbt_put_internal (obt_p, SP_ATTR_ARG_COMMENT, &value); - pr_clear_value (&value); - if (err != NO_ERROR) - { - goto error; - } - - object_p = dbt_finish_object (obt_p); - if (!object_p) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - goto error; - } - obt_p = NULL; - - err = locator_flush_instance (object_p); - if (err != NO_ERROR) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - obj_delete (object_p); - goto error; - } - - *mop_p = object_p; - - AU_ENABLE (save); - return NO_ERROR; - -error: - if (obt_p) - { - dbt_abort_object (obt_p); - } - - AU_ENABLE (save); - return err; -} - -/* - * jsp_check_stored_procedure_name - - * return: java stored procedure name - * str(in) : - * - * Note: convert lowercase - */ - -static char * -jsp_check_stored_procedure_name (const char *str) -{ - char buffer[SM_MAX_IDENTIFIER_LENGTH + 2]; - char *name = NULL; - - sm_downcase_name (str, buffer, SM_MAX_IDENTIFIER_LENGTH); - name = strdup (buffer); - - return name; -} - -/* - * jsp_add_stored_procedure - - * return: Error ID - * name(in): jsp name - * type(in): type - * ret_type(in): return type - * param_list(in): parameter list - * java_method(in): - * comment(in): - * - * Note: - */ - -static int -jsp_add_stored_procedure (const char *name, const PT_MISC_TYPE type, const PT_TYPE_ENUM return_type, - PT_NODE * param_list, const char *java_method, const char *comment) -{ - DB_OBJECT *classobj_p, *object_p; - DB_OTMPL *obt_p = NULL; - DB_VALUE value, v; - DB_SET *param = NULL; - int i, save; - int err; - PT_NODE *node_p; - PT_NAME_INFO name_info; - bool has_savepoint = false; - char *checked_name; - const char *arg_comment; - DB_TYPE return_type_value; - - if (java_method == NULL) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVAILD_JAVA_METHOD, 0); - return er_errid (); - } - - AU_DISABLE (save); - - checked_name = jsp_check_stored_procedure_name (name); - - classobj_p = db_find_class (SP_CLASS_NAME); - - if (classobj_p == NULL) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - goto error; - } - - err = tran_system_savepoint (SAVEPOINT_ADD_STORED_PROC); - if (err != NO_ERROR) - { - goto error; - } - has_savepoint = true; - - obt_p = dbt_create_object_internal (classobj_p); - if (!obt_p) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - goto error; - } - - db_make_string (&value, checked_name); - err = dbt_put_internal (obt_p, SP_ATTR_NAME, &value); - pr_clear_value (&value); - - if (err != NO_ERROR) - { - goto error; - } - - db_make_int (&value, jsp_map_pt_misc_to_sp_type (type)); - err = dbt_put_internal (obt_p, SP_ATTR_SP_TYPE, &value); - if (err != NO_ERROR) - { - goto error; - } - - return_type_value = pt_type_enum_to_db (return_type); - if (jsp_check_return_type_supported (return_type_value) != NO_ERROR) - { - err = er_errid (); - goto error; - } - - db_make_int (&value, (int) return_type_value); - err = dbt_put_internal (obt_p, SP_ATTR_RETURN_TYPE, &value); - if (err != NO_ERROR) - { - goto error; - } - - param = set_create_sequence (0); - if (param == NULL) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - goto error; - } - - for (node_p = param_list, i = 0; node_p != NULL; node_p = node_p->next) - { - MOP mop = NULL; - - if (jsp_check_param_type_supported (node_p) != NO_ERROR) - { - err = er_errid (); - goto error; - } - - name_info = node_p->info.sp_param.name->info.name; - - arg_comment = (char *) PT_NODE_SP_ARG_COMMENT (node_p); - - err = - jsp_add_stored_procedure_argument (&mop, checked_name, name_info.original, i, node_p->type_enum, - node_p->info.sp_param.mode, arg_comment); - if (err != NO_ERROR) - { - goto error; - } - - db_make_object (&v, mop); - err = set_put_element (param, i++, &v); - pr_clear_value (&v); - - if (err != NO_ERROR) - { - goto error; - } - } - - db_make_sequence (&value, param); - err = dbt_put_internal (obt_p, SP_ATTR_ARGS, &value); - pr_clear_value (&value); - param = NULL; - if (err != NO_ERROR) - { - goto error; - } - - db_make_int (&value, i); - err = dbt_put_internal (obt_p, SP_ATTR_ARG_COUNT, &value); - if (err != NO_ERROR) - { - goto error; - } - - db_make_int (&value, SP_LANG_JAVA); - err = dbt_put_internal (obt_p, SP_ATTR_LANG, &value); - if (err != NO_ERROR) - { - goto error; - } - - db_make_string (&value, java_method); - err = dbt_put_internal (obt_p, SP_ATTR_TARGET, &value); - pr_clear_value (&value); - if (err != NO_ERROR) - { - goto error; - } - - db_make_object (&value, Au_user); - err = dbt_put_internal (obt_p, SP_ATTR_OWNER, &value); - pr_clear_value (&value); - if (err != NO_ERROR) - { - goto error; - } - - db_make_string (&value, comment); - err = dbt_put_internal (obt_p, SP_ATTR_COMMENT, &value); - pr_clear_value (&value); - if (err != NO_ERROR) - { - goto error; - } - - object_p = dbt_finish_object (obt_p); - if (!object_p) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - goto error; - } - obt_p = NULL; - - err = locator_flush_instance (object_p); - if (err != NO_ERROR) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - obj_delete (object_p); - goto error; - } - - free_and_init (checked_name); - AU_ENABLE (save); - return NO_ERROR; - -error: - if (param) - set_free (param); - - if (obt_p) - { - dbt_abort_object (obt_p); - } - - if (has_savepoint) - { - tran_abort_upto_system_savepoint (SAVEPOINT_ADD_STORED_PROC); - } - - free_and_init (checked_name); - AU_ENABLE (save); - - return err; -} - -/* - * drop_stored_procedure - - * return: Error code - * name(in): jsp name - * expected_type(in): - * - * Note: - */ - -static int -drop_stored_procedure (const char *name, PT_MISC_TYPE expected_type) -{ - MOP sp_mop, arg_mop, owner; - DB_VALUE sp_type_val, arg_cnt_val, args_val, owner_val, temp; - SP_TYPE_ENUM real_type; - DB_SET *arg_set_p; - int save, i, arg_cnt; - int err; - - AU_DISABLE (save); - - db_make_null (&args_val); - db_make_null (&owner_val); - - sp_mop = jsp_find_stored_procedure (name); - if (sp_mop == NULL) - { - assert (er_errid () != NO_ERROR); - err = er_errid (); - goto error; - } - - err = db_get (sp_mop, SP_ATTR_OWNER, &owner_val); - if (err != NO_ERROR) - { - goto error; - } - owner = db_get_object (&owner_val); - - if (!ws_is_same_object (owner, Au_user) && !au_is_dba_group_member (Au_user)) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_DROP_NOT_ALLOWED, 0); - err = er_errid (); - goto error; - } - - err = db_get (sp_mop, SP_ATTR_SP_TYPE, &sp_type_val); - if (err != NO_ERROR) - { - goto error; - } - - real_type = (SP_TYPE_ENUM) db_get_int (&sp_type_val); - if (real_type != jsp_map_pt_misc_to_sp_type (expected_type)) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_TYPE, 2, name, - real_type == SP_TYPE_FUNCTION ? "FUNCTION" : "PROCEDURE"); - - err = er_errid (); - goto error; - } - - err = db_get (sp_mop, SP_ATTR_ARG_COUNT, &arg_cnt_val); - if (err != NO_ERROR) - { - goto error; - } - - arg_cnt = db_get_int (&arg_cnt_val); - - err = db_get (sp_mop, SP_ATTR_ARGS, &args_val); - if (err != NO_ERROR) - { - goto error; - } - - arg_set_p = db_get_set (&args_val); - - for (i = 0; i < arg_cnt; i++) - { - set_get_element (arg_set_p, i, &temp); - arg_mop = db_get_object (&temp); - err = obj_delete (arg_mop); - pr_clear_value (&temp); - if (err != NO_ERROR) - { - goto error; - } - } - - err = obj_delete (sp_mop); - -error: - AU_ENABLE (save); - - pr_clear_value (&args_val); - pr_clear_value (&owner_val); - - return err; -} - -/* - * jsp_set_prepare_call - - * return: none - * - * Note: - */ - -void -jsp_set_prepare_call (void) -{ - int depth = tran_get_libcas_depth (); - is_prepare_call[depth] = true; -} - -/* - * jsp_unset_prepare_call - - * return: none - * - * Note: - */ - -void -jsp_unset_prepare_call (void) -{ - int depth = tran_get_libcas_depth (); - is_prepare_call[depth] = false; -} - -/* - * jsp_is_prepare_call - - * return: bool - * - * Note: - */ - -bool -jsp_is_prepare_call () -{ - int depth = tran_get_libcas_depth (); - return is_prepare_call[depth]; -} - -/* - * jsp_make_method_sig_list () - converts a parse expression tree list of - * method calls to method signature list - * return: A NULL return indicates a (memory) error occurred - * parser(in): - * node_list(in): should be parse method nodes - * subquery_as_attr_list(in): - */ -static int -jsp_make_method_sig_list (PARSER_CONTEXT * parser, PT_NODE * node, method_sig_list & sig_list) -{ - int error = NO_ERROR; - int save; - DB_VALUE method, param_cnt_val, mode, arg_type, temp, result_type; - - int sig_num_args = pt_length_of_list (node->info.method_call.arg_list); - std::vector < int >sig_arg_mode; - std::vector < int >sig_arg_type; - int sig_result_type; - - METHOD_SIG *sig = nullptr; - - db_make_null (&method); - db_make_null (¶m_cnt_val); - db_make_null (&mode); - db_make_null (&arg_type); - db_make_null (&temp); - db_make_null (&result_type); - - { - char *parsed_method_name = (char *) node->info.method_call.method_name->info.name.original; - DB_OBJECT *mop_p = jsp_find_stored_procedure (parsed_method_name); - AU_DISABLE (save); - if (mop_p) - { - /* check java stored prcedure target */ - error = db_get (mop_p, SP_ATTR_TARGET, &method); - if (error != NO_ERROR) - { - goto end; - } - - /* check arg count */ - error = db_get (mop_p, SP_ATTR_ARG_COUNT, ¶m_cnt_val); - if (error != NO_ERROR) - { - goto end; - } - - int param_cnt = db_get_int (¶m_cnt_val); - if (sig_num_args != param_cnt) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_PARAM_COUNT, 2, param_cnt, sig_num_args); - error = er_errid (); - goto end; - } - - DB_VALUE args; - /* arg_mode, arg_type */ - error = db_get (mop_p, SP_ATTR_ARGS, &args); - if (error != NO_ERROR) - { - goto end; - } - - DB_SET *param_set = db_get_set (&args); - for (int i = 0; i < sig_num_args; i++) - { - set_get_element (param_set, i, &temp); - DB_OBJECT *arg_mop_p = db_get_object (&temp); - if (arg_mop_p) - { - error = db_get (arg_mop_p, SP_ATTR_MODE, &mode); - int arg_mode = db_get_int (&mode); - - error = jsp_check_out_param_in_query (parser, node, arg_mode); - - if (error == NO_ERROR) - { - sig_arg_mode.push_back (arg_mode); - } - else - { - goto end; - } - - error = db_get (arg_mop_p, SP_ATTR_DATA_TYPE, &arg_type); - if (error == NO_ERROR) - { - int type_val = db_get_int (&arg_type); - if (type_val == DB_TYPE_RESULTSET && !jsp_is_prepare_call ()) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_RETURN_RESULTSET, 0); - error = er_errid (); - goto end; - } - sig_arg_type.push_back (type_val); - } - else - { - goto end; - } - - pr_clear_value (&mode); - pr_clear_value (&arg_type); - pr_clear_value (&temp); - } - } - pr_clear_value (&args); - - /* result type */ - error = db_get (mop_p, SP_ATTR_RETURN_TYPE, &result_type); - if (error != NO_ERROR) - { - goto end; - } - sig_result_type = db_get_int (&result_type); - if (sig_result_type == DB_TYPE_RESULTSET && !jsp_is_prepare_call ()) - { - er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_RETURN_RESULTSET, 0); - error = er_errid (); - goto end; - } - } - else - { - error = er_errid (); - goto end; - } - - sig = sig_list.method_sig = (METHOD_SIG *) db_private_alloc (NULL, sizeof (METHOD_SIG)); - if (sig) - { - sig->next = nullptr; - sig->num_method_args = sig_num_args; - sig->method_type = METHOD_TYPE_JAVA_SP; - - const char *method_name = db_get_string (&method); - int method_name_len = db_get_string_size (&method); - - sig->method_name = (char *) db_private_alloc (NULL, method_name_len + 1); - if (!sig->method_name) - { - error = ER_OUT_OF_VIRTUAL_MEMORY; - goto end; - } - - memcpy (sig->method_name, method_name, method_name_len); - sig->method_name[method_name_len] = 0; - - - sig->method_arg_pos = (int *) db_private_alloc (NULL, (sig_num_args + 1) * sizeof (int)); - if (!sig->method_arg_pos) - { - error = ER_OUT_OF_VIRTUAL_MEMORY; - goto end; - } - - for (int i = 0; i < sig_num_args + 1; i++) - { - sig->method_arg_pos[i] = i; - } - - - sig->arg_info.arg_mode = (int *) db_private_alloc (NULL, (sig_num_args + 1) * sizeof (int)); - if (!sig->arg_info.arg_mode) - { - error = ER_OUT_OF_VIRTUAL_MEMORY; - goto end; - } - - sig->arg_info.arg_type = (int *) db_private_alloc (NULL, (sig_num_args + 1) * sizeof (int)); - if (!sig->arg_info.arg_type) - { - error = ER_OUT_OF_VIRTUAL_MEMORY; - goto end; - } - - for (int i = 0; i < sig_num_args; i++) - { - sig->arg_info.arg_mode[i] = sig_arg_mode[i]; - sig->arg_info.arg_type[i] = sig_arg_type[i]; - } - - sig->arg_info.result_type = sig_result_type; - - sig_list.num_methods = 1; - } - else - { - error = ER_OUT_OF_VIRTUAL_MEMORY; - goto end; - } - } - -end: - AU_ENABLE (save); - if (error != NO_ERROR) - { - if (sig) - { - sig->freemem (); - } - sig_list.method_sig = nullptr; - sig_list.num_methods = 0; - } - - pr_clear_value (&method); - pr_clear_value (¶m_cnt_val); - pr_clear_value (&result_type); - - return error; -} - -/* - * pt_to_method_arglist () - converts a parse expression tree list of - * method call arguments to method argument array - * return: A NULL on error occurred - * parser(in): - * target(in): - * node_list(in): should be parse name nodes - * subquery_as_attr_list(in): - */ -static int * -jsp_make_method_arglist (PARSER_CONTEXT * parser, PT_NODE * node_list) -{ - int *arg_list = NULL; - int i = 0; - int num_args = pt_length_of_list (node_list); - PT_NODE *node; - - arg_list = (int *) db_private_alloc (NULL, num_args * sizeof (int)); - if (!arg_list) - { - return NULL; - } - - for (node = node_list; node != NULL; node = node->next) - { - arg_list[i] = i; - i++; - /* - arg_list[i] = pt_find_attribute (parser, node, subquery_as_attr_list); - if (arg_list[i] == -1) - { - return NULL; - } - i++; - */ - } - - return arg_list; -} diff --git a/src/sp/jsp_cl.cpp b/src/sp/jsp_cl.cpp new file mode 100644 index 00000000000..873446a8d6f --- /dev/null +++ b/src/sp/jsp_cl.cpp @@ -0,0 +1,2438 @@ +/* + * Copyright 2008 Search Solution Corporation + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * jsp_cl.cpp - Java Stored Procedure Client Module Source + */ + +#ident "$Id$" + +#include "config.h" + +#include +#if !defined(WINDOWS) +#include +#else /* not WINDOWS */ +#include +#endif /* not WINDOWS */ + +#include +#include +#include +#include +#include +#include + +#include "authenticate.h" +#include "error_manager.h" +#include "memory_alloc.h" +#include "dbtype.h" +#include "parser.h" +#include "parser_message.h" +#include "object_domain.h" +#include "object_primitive.h" +#include "object_representation.h" +#include "db.h" +#include "object_accessor.h" +#include "set_object.h" +#include "locator_cl.h" +#include "transaction_cl.h" +#include "schema_manager.h" +#include "numeric_opfunc.h" +#include "jsp_cl.h" +#include "system_parameter.h" +#include "network_interface_cl.h" +#include "unicode_support.h" +#include "dbtype.h" +#include "pl_comm.h" +#include "pl_struct_compile.hpp" +#include "sp_catalog.hpp" +#include "authenticate_access_auth.hpp" +#include "pl_signature.hpp" +#include "oid.h" +#include "string_buffer.hpp" +#include "db_value_printer.hpp" +#include "execute_statement.h" + +#define PT_NODE_SP_NAME(node) \ + (((node)->info.sp.name == NULL) ? "" : \ + (node)->info.sp.name->info.name.original) + +#define PT_NODE_SP_TYPE(node) \ + ((node)->info.sp.type) + +#define PT_NODE_SP_RETURN_TYPE(node) \ + ((node)->info.sp.ret_type->info.name.original) + +#define PT_NODE_SP_BODY(node) \ + ((node)->info.sp.body) + +#define PT_NODE_SP_LANG(node) \ + ((node)->info.sp.body->info.sp_body.lang) + +#define PT_NODE_SP_ARGS(node) \ + ((node)->info.sp.param_list) + +#define PT_NODE_SP_DIRECT(node) \ + ((node)->info.sp.body->info.sp_body.direct) + +#define PT_NODE_SP_IMPL(node) \ + ((node)->info.sp.body->info.sp_body.impl->info.value.data_value.str->bytes) + +#define PT_NODE_SP_JAVA_METHOD(node) \ + ((node)->info.sp.body->info.sp_body.decl->info.value.data_value.str->bytes) + +#define PT_NODE_SP_AUTHID(node) \ + ((node)->info.sp.auth_id) + +#define PT_NODE_SP_COMMENT(node) \ + (((node)->info.sp.comment == NULL) ? "" : \ + (char *) (node)->info.sp.comment->info.value.data_value.str->bytes) + +#define PT_NODE_SP_ARG_NAME(node) \ + (((node)->info.sp_param.name == NULL) ? "" : \ + (node)->info.sp_param.name->info.name.original) + +#define PT_NODE_SP_ARG_COMMENT(node) \ + (((node)->info.sp_param.comment == NULL) ? "" : \ + (char *) (node)->info.sp_param.comment->info.value.data_value.str->bytes) + +#define MAX_CALL_COUNT 16 + +#define MAX_ARG_COUNT 64 + +static int server_port = -1; +static int call_cnt = 0; +static bool is_prepare_call[MAX_CALL_COUNT] = { false, }; + +static SP_TYPE_ENUM jsp_map_pt_misc_to_sp_type (PT_MISC_TYPE pt_enum); +static SP_MODE_ENUM jsp_map_pt_misc_to_sp_mode (PT_MISC_TYPE pt_enum); +static PT_MISC_TYPE jsp_map_sp_type_to_pt_misc (SP_TYPE_ENUM sp_type); +static SP_DIRECTIVE_ENUM jsp_map_pt_to_sp_authid (PT_MISC_TYPE pt_authid); + +static char *jsp_check_stored_procedure_name (const char *str); +static int jsp_check_overflow_args (PARSER_CONTEXT *parser, PT_NODE *node, int num_params, int num_args); +static int jsp_check_out_param_in_query (PARSER_CONTEXT *parser, PT_NODE *node, int arg_mode); +static int jsp_check_param_type_supported (DB_TYPE type, int mode); + +static int drop_stored_procedure (const char *name, SP_TYPE_ENUM expected_type); +static int drop_stored_procedure_code (const char *name); +static int alter_stored_procedure_code (PARSER_CONTEXT *parser, MOP sp_mop, const char *name, const char *owner_str, + int sp_recompile); + +static int jsp_default_value_string (PARSER_CONTEXT *parser, PT_NODE *node, std::string &out); +static int check_execute_authorization (const MOP sp_obj, const DB_AUTH au_type); + +extern bool ssl_client; + +/* + * jsp_is_exist_stored_procedure + * return: name is exist then return true + * else return false + * name(in): find java stored procedure name + * + * Note: + */ + +int +jsp_is_exist_stored_procedure (const char *name) +{ + MOP mop = NULL; + + mop = jsp_find_stored_procedure (name, DB_AUTH_NONE); + er_clear (); + + return mop != NULL; +} + +/* + * jsp_find_stored_procedure + * return: MOP + * name(in): find java stored procedure name + * purpose(in): DB_AUTH_NONE or DB_AUTH_SELECT + * + * Note: + */ + +MOP +jsp_find_stored_procedure (const char *name, DB_AUTH purpose) +{ + MOP mop = NULL; + DB_VALUE value; + int save, err = NO_ERROR; + char *checked_name; + + if (!name) + { + return NULL; + } + + AU_DISABLE (save); + + checked_name = jsp_check_stored_procedure_name (name); + db_make_string (&value, checked_name); + mop = db_find_unique (db_find_class (SP_CLASS_NAME), SP_ATTR_UNIQUE_NAME, &value); + + if (er_errid () == ER_OBJ_OBJECT_NOT_FOUND) + { + er_clear (); + + /* This is the case when the loaddb utility is executed with the --no-user-specified-name option as the dba user. */ + if (db_get_client_type () == DB_CLIENT_TYPE_ADMIN_LOADDB_COMPAT) + { + err = jsp_find_sp_of_another_owner (name, &mop); + } + else + { + err = ER_SP_NOT_EXIST; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, err, 1, checked_name); + } + } + + if (mop) + { + err = check_execute_authorization (mop, purpose); + } + + if (err != NO_ERROR) + { + mop = NULL; + } + + free_and_init (checked_name); + AU_ENABLE (save); + + return mop; +} + +/* + * jsp_find_stored_procedure_code + * return: MOP + * name(in): find java stored procedure name + * + * Note: + */ + +MOP +jsp_find_stored_procedure_code (const char *name) +{ + MOP mop = NULL; + DB_VALUE value; + int save; + + if (!name) + { + return NULL; + } + + AU_DISABLE (save); + + db_make_string (&value, name); + mop = db_find_unique (db_find_class (SP_CODE_CLASS_NAME), SP_ATTR_CLS_NAME, &value); + + if (er_errid () == ER_OBJ_OBJECT_NOT_FOUND) + { + er_clear (); + } + + AU_ENABLE (save); + + return mop; +} + +/* + * jsp_find_sp_of_another_owner + * return: if fail return error code + * name(in): find java stored procedure name + * return_mop(in): retrieves the name of a java stored procedure and returns its MOP value. + * + * Note: This is a function for finding the unique_name of an SP when running the loaddb utility with the --no-user-specified-name option as a dba user. + */ + +int +jsp_find_sp_of_another_owner (const char *name, MOP *return_mop) +{ + int error = NO_ERROR; + DB_VALUE value; + char other_class_name[DB_MAX_IDENTIFIER_LENGTH]; + other_class_name[0] = '\0'; + *return_mop = NULL; + + error = do_find_stored_procedure_by_query (name, other_class_name, DB_MAX_IDENTIFIER_LENGTH); + if (other_class_name[0] != '\0') + { + db_make_string (&value, other_class_name); + *return_mop = db_find_unique (db_find_class (SP_CLASS_NAME), SP_ATTR_UNIQUE_NAME, &value); + if (er_errid () == ER_OBJ_OBJECT_NOT_FOUND) + { + error = ER_SP_NOT_EXIST; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, other_class_name); + } + } + + return error; +} + +/* + * jsp_check_out_param_in_query + * + * Note: + */ + +static int +jsp_check_out_param_in_query (PARSER_CONTEXT *parser, PT_NODE *node, int arg_mode) +{ + int error = NO_ERROR; + + assert ((node) && (node)->node_type == PT_METHOD_CALL); + + if (node->info.method_call.call_or_expr != PT_IS_CALL_STMT) + { + // check out parameters + if (arg_mode != SP_MODE_IN) + { + PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_SP_OUT_ARGS_EXISTS_IN_QUERY, + node->info.method_call.method_name->info.name.original); + error = ER_PT_SEMANTIC; + } + } + + return error; +} + +/* + * jsp_check_param_type_supported + * + * Note: + */ + +static int +jsp_check_param_type_supported (DB_TYPE type, int mode) +{ + switch (type) + { + case DB_TYPE_INTEGER: + case DB_TYPE_FLOAT: + case DB_TYPE_DOUBLE: + case DB_TYPE_STRING: + case DB_TYPE_OBJECT: + case DB_TYPE_SET: + case DB_TYPE_MULTISET: + case DB_TYPE_SEQUENCE: + case DB_TYPE_TIME: + case DB_TYPE_TIMESTAMP: + case DB_TYPE_DATE: + case DB_TYPE_MONETARY: + case DB_TYPE_SHORT: + case DB_TYPE_NUMERIC: + case DB_TYPE_CHAR: + case DB_TYPE_BIGINT: + case DB_TYPE_DATETIME: + return NO_ERROR; + break; + + case DB_TYPE_RESULTSET: + if (mode != SP_MODE_OUT) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_INPUT_RESULTSET, 0); + } + else if (!jsp_is_prepare_call ()) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_RETURN_RESULTSET, 0); + } + else + { + return NO_ERROR; + } + break; + + default: + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_SUPPORTED_ARG_TYPE, 1, pr_type_name (type)); + break; + } + + return er_errid (); +} + +/* + * jsp_check_return_type_supported + * + * Note: + */ + +int +jsp_check_return_type_supported (DB_TYPE type) +{ + switch (type) + { + case DB_TYPE_NULL: + case DB_TYPE_INTEGER: + case DB_TYPE_FLOAT: + case DB_TYPE_DOUBLE: + case DB_TYPE_STRING: + case DB_TYPE_OBJECT: + case DB_TYPE_SET: + case DB_TYPE_MULTISET: + case DB_TYPE_SEQUENCE: + case DB_TYPE_TIME: + case DB_TYPE_TIMESTAMP: + case DB_TYPE_DATE: + case DB_TYPE_MONETARY: + case DB_TYPE_SHORT: + case DB_TYPE_NUMERIC: + case DB_TYPE_CHAR: + case DB_TYPE_BIGINT: + case DB_TYPE_DATETIME: + return NO_ERROR; + case DB_TYPE_RESULTSET: + if (!jsp_is_prepare_call ()) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_RETURN_RESULTSET, 0); + } + break; + + default: + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_SUPPORTED_RETURN_TYPE, 1, pr_type_name (type)); + break; + } + + return er_errid (); +} + +/* + * jsp_get_return_type - Return Java Stored Procedure Type + * return: if fail return error code + * else return Java Stored Procedure Type + * name(in): java stored procedure name + * + * Note: + */ + +int +jsp_get_return_type (const char *name) +{ + DB_OBJECT *mop_p; + DB_VALUE return_type; + int err; + int save; + + AU_DISABLE (save); + + mop_p = jsp_find_stored_procedure (name, DB_AUTH_NONE); + if (mop_p == NULL) + { + AU_ENABLE (save); + + assert (er_errid () != NO_ERROR); + return er_errid (); + } + + err = db_get (mop_p, SP_ATTR_RETURN_TYPE, &return_type); + if (err != NO_ERROR) + { + AU_ENABLE (save); + return err; + } + + AU_ENABLE (save); + return db_get_int (&return_type); +} + +/* + * jsp_get_sp_type - Return Java Stored Procedure Type + * return: if fail return error code + * else return Java Stored Procedure Type + * name(in): java stored procedure name + * + * Note: + */ + +int +jsp_get_sp_type (const char *name) +{ + DB_OBJECT *mop_p; + DB_VALUE sp_type_val; + int err; + int save; + + AU_DISABLE (save); + + mop_p = jsp_find_stored_procedure (name, DB_AUTH_NONE); + if (mop_p == NULL) + { + AU_ENABLE (save); + + assert (er_errid () != NO_ERROR); + return er_errid (); + } + + /* check type */ + err = db_get (mop_p, SP_ATTR_SP_TYPE, &sp_type_val); + if (err != NO_ERROR) + { + AU_ENABLE (save); + return err; + } + + AU_ENABLE (save); + return jsp_map_sp_type_to_pt_misc ((SP_TYPE_ENUM) db_get_int (&sp_type_val)); +} + +MOP +jsp_get_owner (MOP mop_p) +{ + int save; + DB_VALUE value; + + AU_DISABLE (save); + + /* check type */ + int err = db_get (mop_p, SP_ATTR_OWNER, &value); + if (err != NO_ERROR) + { + AU_ENABLE (save); + return NULL; + } + + MOP owner = db_get_object (&value); + + AU_ENABLE (save); + return owner; +} + +char * +jsp_get_name (MOP mop_p) +{ + int save; + DB_VALUE value; + char *res = NULL; + + AU_DISABLE (save); + + /* check type */ + int err = db_get (mop_p, SP_ATTR_NAME, &value); + if (err != NO_ERROR) + { + AU_ENABLE (save); + return NULL; + } + + res = ws_copy_string (db_get_string (&value)); + pr_clear_value (&value); + + AU_ENABLE (save); + return res; +} + +char * +jsp_get_unique_name (MOP mop_p, char *buf, int buf_size) +{ + int save; + DB_VALUE value; + int err = NO_ERROR; + + assert (buf != NULL); + assert (buf_size > 0); + + if (mop_p == NULL) + { + ERROR_SET_WARNING (err, ER_SM_INVALID_ARGUMENTS); + buf[0] = '\0'; + return NULL; + } + + AU_DISABLE (save); + + /* check type */ + err = db_get (mop_p, SP_ATTR_UNIQUE_NAME, &value); + if (err != NO_ERROR) + { + AU_ENABLE (save); + return NULL; + } + + strncpy (buf, db_get_string (&value), buf_size); + pr_clear_value (&value); + + AU_ENABLE (save); + return buf; +} + +/* + * jsp_get_owner_name - Return Java Stored Procedure'S Owner nmae + * return: if fail return MULL + * else return Java Stored Procedure Type + * name(in): java stored procedure name + * + * Note: + */ + +char * +jsp_get_owner_name (const char *name, char *buf, int buf_size) +{ + DB_OBJECT *mop_p; + DB_VALUE value; + int err; + int save; + + assert (buf != NULL); + assert (buf_size > 0); + + if (name == NULL || name[0] == '\0') + { + ERROR_SET_WARNING (err, ER_SM_INVALID_ARGUMENTS); + buf[0] = '\0'; + return NULL; + } + + AU_DISABLE (save); + + mop_p = jsp_find_stored_procedure (name, DB_AUTH_NONE); + if (mop_p == NULL) + { + AU_ENABLE (save); + + assert (er_errid () != NO_ERROR); + return NULL; + } + + /* check type */ + err = db_get (mop_p, SP_ATTR_OWNER, &value); + if (err != NO_ERROR) + { + AU_ENABLE (save); + return NULL; + } + + MOP owner = db_get_object (&value); + if (owner != NULL) + { + DB_VALUE value2; + err = db_get (owner, "name", &value2); + if (err == NO_ERROR) + { + strncpy (buf, db_get_string (&value2), buf_size); + } + pr_clear_value (&value2); + } + pr_clear_value (&value); + + AU_ENABLE (save); + return buf; +} + + + +static PT_MISC_TYPE +jsp_map_sp_type_to_pt_misc (SP_TYPE_ENUM sp_type) +{ + if (sp_type == SP_TYPE_PROCEDURE) + { + return PT_SP_PROCEDURE; + } + else + { + return PT_SP_FUNCTION; + } +} + +static int +jsp_evaluate_arguments (PARSER_CONTEXT *parser, PT_NODE *statement, + std::vector > &args) +{ + assert (statement); + assert (statement->node_type == PT_METHOD_CALL); + + PT_NODE *vc = statement->info.method_call.arg_list; + while (vc) + { + DB_VALUE *db_value; + + /* + * Don't clone host vars; they may actually be acting as output variables (e.g., a character array that is + * intended to receive bytes from the method), and cloning will ensure that the results never make it to the + * expected area. Since pt_evaluate_tree() always clones its db_values we must not use pt_evaluate_tree() to + * extract the db_value from a host variable; instead extract it ourselves. */ + if (PT_IS_CONST (vc)) + { + db_value = pt_value_to_db (parser, vc); + } + else + { + db_value = (DB_VALUE *) malloc (sizeof (DB_VALUE)); + if (db_value == NULL) + { + goto exit_on_error; + } + + db_make_null (db_value); + + /* must call pt_evaluate_tree */ + pt_evaluate_tree_having_serial (parser, vc, db_value, 1); + if (pt_has_error (parser)) + { + /* to maintain the list to free all the allocated */ + db_value_clear (db_value); + goto exit_on_error; + } + } + + args.emplace_back (std::ref (*db_value)); + vc = vc->next; + } + + return NO_ERROR; + +exit_on_error: + + for (DB_VALUE &val : args) + { + db_value_clear (&val); + } + args.clear (); + + return ER_FAILED; +} + +/* + * jsp_call_stored_procedure - call java stored procedure in constant folding + * return: call jsp failed return error code + * parser(in/out): parser environment + * statement(in): a statement node + * + * Note: + */ + +int +jsp_call_stored_procedure (PARSER_CONTEXT *parser, PT_NODE *statement) +{ + int error = NO_ERROR; + PT_NODE *method; + const char *method_name; + if (!statement || ! (method = statement->info.method_call.method_name) || method->node_type != PT_NAME) + { + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ARGUMENTS, 0); + return er_errid (); + } + + DB_VALUE ret_value; + db_make_null (&ret_value); + + /* call sp */ + std::vector > args; + cubpl::pl_signature sig; + error = jsp_make_pl_signature (parser, statement, NULL, sig); + if (error == NO_ERROR) + { + PT_NODE *default_next_node_list = jsp_get_default_expr_node_list (parser, sig); + if (default_next_node_list != NULL) + { + error = qp_get_server_info (parser, SI_SYS_DATETIME); + } + statement->info.method_call.arg_list = parser_append_node (default_next_node_list, + statement->info.method_call.arg_list); + error = jsp_evaluate_arguments (parser, statement, args); + if (pt_has_error (parser)) + { + pt_report_to_ersys (parser, PT_SEMANTIC); + error = er_errid (); + } + } + + if (error == NO_ERROR && locator_get_sig_interrupt () == 0) + { + std::vector out_args; + error = pl_call (sig, args, out_args, ret_value); + if (error == NO_ERROR) + { + for (int i = 0, j = 0; i < sig.arg.arg_size; i++) + { + if (sig.arg.arg_mode[i] == SP_MODE_IN) + { + continue; + } + + DB_VALUE &arg = args[i]; + DB_VALUE &out_arg = out_args[j++]; + + db_value_clear (&arg); + db_value_clone (&out_arg, &arg); + db_value_clear (&out_arg); + } + } + } + + PT_NODE *vc = statement->info.method_call.arg_list; + for (int i = 0; i < (int) args.size () && vc; i++) + { + if (!PT_IS_CONST (vc)) + { + DB_VALUE &arg = args[i]; + db_value_clear (&arg); + free (&arg); + } + vc = vc->next; + } + + if (error == NO_ERROR) + { + /* Save the method result and its domain */ + statement->etc = (void *) db_value_copy (&ret_value); + statement = pt_bind_type_from_dbval (parser, statement, &ret_value); + + PT_NODE *into = statement->info.method_call.to_return_var; + + const char *into_label; + if (into != NULL && into->node_type == PT_NAME && (into_label = into->info.name.original) != NULL) + { + /* create another DB_VALUE of the new instance for the label_table */ + DB_VALUE *ins_value = db_value_copy (&ret_value); + error = pt_associate_label_with_value_check_reference (into_label, ins_value); + } + } + +#if defined (CS_MODE) + db_value_clear (&ret_value); +#endif + + return error; +} + +/* + * jsp_drop_stored_procedure - drop java stored procedure + * return: Error code + * parser(in/out): parser environment + * statement(in): a statement node + * + * Note: + */ + +int +jsp_drop_stored_procedure (PARSER_CONTEXT *parser, PT_NODE *statement) +{ + const char *name; + PT_MISC_TYPE type; + PT_NODE *name_list, *p; + int i; + int err = NO_ERROR; + + CHECK_MODIFICATION_ERROR (); + + if (prm_get_bool_value (PRM_ID_BLOCK_DDL_STATEMENT)) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_BLOCK_DDL_STMT, 0); + return ER_BLOCK_DDL_STMT; + } + + name_list = statement->info.sp.name; + type = PT_NODE_SP_TYPE (statement); + + for (p = name_list, i = 0; p != NULL; p = p->next) + { + name = (char *) p->info.name.original; + if (name == NULL || name[0] == '\0') + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_NAME, 0); + return er_errid (); + } + + err = drop_stored_procedure (name, jsp_map_pt_misc_to_sp_type (type)); + if (err != NO_ERROR) + { + break; + } + } + + return err; +} + +/* + * jsp_default_value_string + * return: + * parser(in/out): parser environment + * statement(in): a default_value node + * + * Note: + */ +static int +jsp_default_value_string (PARSER_CONTEXT *parser, PT_NODE *node, std::string &out) +{ + int error = NO_ERROR; + + DB_DEFAULT_EXPR default_expr; + pt_get_default_expression_from_data_default_node (parser, node, &default_expr); + + out.clear (); + if (default_expr.default_expr_type != DB_DEFAULT_NONE) + { + if (default_expr.default_expr_type == NULL_DEFAULT_EXPRESSION_OPERATOR) + { + DB_VALUE *value = pt_value_to_db (parser, node->info.data_default.default_value); + if (!DB_IS_NULL (value)) + { + string_buffer sb; + sb.clear (); + db_sprint_value (value, sb); + + out.append (sb.get_buffer ()); + } + else + { + // empty out consider as NULL + } + } + else + { + if (default_expr.default_expr_op == T_TO_CHAR) + { + out.append ("TO_CHAR("); + } + + const char *default_value_expr_type_string = db_default_expression_string (default_expr.default_expr_type); + if (default_value_expr_type_string != NULL) + { + out.append (default_value_expr_type_string); + } + else + { + out.append (parser_print_tree (parser, node)); + } + + if (default_expr.default_expr_op == T_TO_CHAR) + { + if (default_expr.default_expr_format != NULL) + { + out.append (", \'"); + out.append (default_expr.default_expr_format); + out.append ("\'"); + } + + out.append (")"); + } + } + } + else + { + DB_VALUE *value = pt_value_to_db (parser, node->info.data_default.default_value); + if (!DB_IS_NULL (value)) + { + string_buffer sb; + sb.clear (); + db_sprint_value (value, sb); + + out.append (sb.get_buffer ()); + } + else + { + // empty out consider as NULL + } + } + + return error; +} + +/* + * jsp_create_stored_procedure + * return: if failed return error code else execute jsp_add_stored_procedure + * function + * parser(in/out): parser environment + * statement(in): a statement node + * + * Note: + */ + +int +jsp_create_stored_procedure (PARSER_CONTEXT *parser, PT_NODE *statement) +{ + const char *decl = NULL, *comment = NULL; + char owner_name[DB_MAX_USER_LENGTH]; + owner_name[0] = '\0'; + + PT_NODE *param_list, *p; + PT_TYPE_ENUM ret_type = PT_TYPE_NONE; + int lang; + int err = NO_ERROR; + bool has_savepoint = false; + + PLCSQL_COMPILE_REQUEST compile_request; + PLCSQL_COMPILE_RESPONSE compile_response; + + SP_INFO sp_info; + char *temp; + + CHECK_MODIFICATION_ERROR (); + + if (prm_get_bool_value (PRM_ID_BLOCK_DDL_STATEMENT)) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_BLOCK_DDL_STMT, 0); + return ER_BLOCK_DDL_STMT; + } + + // check PL/CSQL's AUTHID with CURRENT_USER + sp_info.directive = jsp_map_pt_to_sp_authid (PT_NODE_SP_AUTHID (statement)); + sp_info.lang = (SP_LANG_ENUM) PT_NODE_SP_LANG (statement); + if (sp_info.directive == SP_DIRECTIVE_RIGHTS_CALLER && sp_info.lang == SP_LANG_PLCSQL) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVOKERS_RIGHTS_NOT_SUPPORTED, 0); + return er_errid (); + } + + temp = jsp_check_stored_procedure_name (PT_NODE_SP_NAME (statement)); + sp_info.unique_name = temp; + free (temp); + if (sp_info.unique_name.empty ()) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_NAME, 0); + return er_errid (); + } + + sp_info.sp_name = sm_remove_qualifier_name (sp_info.unique_name.data ()); + if (sp_info.sp_name.empty ()) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_NAME, 0); + return er_errid (); + } + + sp_info.sp_type = jsp_map_pt_misc_to_sp_type (PT_NODE_SP_TYPE (statement)); + if (sp_info.sp_type == SP_TYPE_FUNCTION) + { + sp_info.return_type = pt_type_enum_to_db (statement->info.sp.ret_type); + } + else + { + sp_info.return_type = DB_TYPE_NULL; + } + + // set rows for _db_stored_procedure_args + int param_count = 0; + param_list = PT_NODE_SP_ARGS (statement); + for (p = param_list; p != NULL; p = p->next) + { + SP_ARG_INFO arg_info (sp_info.unique_name, sp_info.pkg_name); + + arg_info.index_of = param_count++; + arg_info.arg_name = PT_NODE_SP_ARG_NAME (p); + arg_info.data_type = pt_type_enum_to_db (p->type_enum); + arg_info.mode = jsp_map_pt_misc_to_sp_mode (p->info.sp_param.mode); + + // default value + // coerciable is already checked in semantic_check + PT_NODE *default_value = p->info.sp_param.default_value; + if (default_value) + { + std::string default_value_str; + if (jsp_default_value_string (parser, default_value, default_value_str) == NO_ERROR) + { + if (!default_value_str.empty ()) + { + db_make_string (&arg_info.default_value, ws_copy_string (default_value_str.c_str ())); + } + else + { + db_make_null (&arg_info.default_value); + } + + arg_info.is_optional = true; + } + else + { + ASSERT_ERROR (); + goto error_exit; + } + } + else + { + db_make_null (&arg_info.default_value); + arg_info.is_optional = false; // explicitly + } + + arg_info.comment = (char *) PT_NODE_SP_ARG_COMMENT (p); + + // check # of args constraint + if (param_count > MAX_ARG_COUNT) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_TOO_MANY_ARG_COUNT, 1, sp_info.unique_name.data ()); + goto error_exit; + } + + sp_info.args.push_back (arg_info); + } + + if (sm_qualifier_name (sp_info.unique_name.data (), owner_name, DB_MAX_USER_LENGTH) == NULL) + { + ASSERT_ERROR (); + goto error_exit; + } + + sp_info.owner = owner_name[0] == '\0' ? Au_user : db_find_user (owner_name); + if (sp_info.owner == NULL) + { + // for safeguard: it is already checked in pt_check_create_stored_procedure () + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_AU_INVALID_USER_NAME, 1, owner_name); + goto error_exit; + } + + if (sp_info.lang == SP_LANG_PLCSQL) + { + assert (statement->sql_user_text && statement->sql_user_text_len); + compile_request.code.assign (statement->sql_user_text, statement->sql_user_text_len); + compile_request.owner.assign ((owner_name[0] == '\0') ? au_get_current_user_name () : owner_name); + + // TODO: Only the owner's rights is supported for PL/CSQL + au_perform_push_user (sp_info.owner); + err = plcsql_transfer_file (compile_request, compile_response); + au_perform_pop_user (); + + if (err == NO_ERROR && compile_response.err_code == NO_ERROR) + { + decl = compile_response.java_signature.c_str (); + } + else + { + err = ER_SP_COMPILE_ERROR; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_COMPILE_ERROR, 3, compile_response.err_line, + compile_response.err_column, compile_response.err_msg.c_str ()); + pt_record_error (parser, parser->statement_number, compile_response.err_line, compile_response.err_column, er_msg (), + NULL); + goto error_exit; + } + } + else /* SP_LANG_JAVA */ + { + bool is_direct = PT_NODE_SP_DIRECT (statement); + if (is_direct) + { + // TODO: CBRD-24641 + assert (false); + } + else + { + decl = (const char *) PT_NODE_SP_JAVA_METHOD (statement); + } + } + + if (decl) + { + std::string target = decl; + sp_split_target_signature (target, sp_info.target_class, sp_info.target_method); + } + + sp_info.comment = (char *) PT_NODE_SP_COMMENT (statement); + + if (err != NO_ERROR) + { + goto error_exit; + } + + /* check already exists */ + if (jsp_is_exist_stored_procedure (sp_info.unique_name.data ())) + { + if (statement->info.sp.or_replace) + { + /* drop existing stored procedure */ + err = tran_system_savepoint (SAVEPOINT_CREATE_STORED_PROC); + if (err != NO_ERROR) + { + return err; + } + has_savepoint = true; + + err = drop_stored_procedure (sp_info.unique_name.data (), sp_info.sp_type); + if (err != NO_ERROR) + { + goto error_exit; + } + } + else + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_ALREADY_EXIST, 1, sp_info.unique_name.data ()); + goto error_exit; + } + } + + err = sp_add_stored_procedure (sp_info); + if (err != NO_ERROR) + { + goto error_exit; + } + + if (!compile_request.code.empty ()) + { + SP_CODE_INFO code_info; + + auto now = std::chrono::system_clock::now(); + auto converted_timep = std::chrono::system_clock::to_time_t (now); + std::stringstream stm; + stm << std::put_time (localtime (&converted_timep), "%Y%m%d%H%M%S"); + + code_info.name = sp_info.target_class; + code_info.created_time = stm.str (); + code_info.stype = (sp_info.lang == SP_LANG_PLCSQL) ? SPSC_PLCSQL : SPSC_JAVA; + code_info.scode = compile_request.code; + code_info.otype = compile_response.compiled_type; + code_info.ocode = compile_response.compiled_code; + code_info.owner = sp_info.owner; + + err = sp_add_stored_procedure_code (code_info); + if (err != NO_ERROR) + { + goto error_exit; + } + } + + return NO_ERROR; + +error_exit: + if (has_savepoint) + { + tran_abort_upto_system_savepoint (SAVEPOINT_CREATE_STORED_PROC); + } + + return (err == NO_ERROR) ? er_errid () : err; +} + +/* + * jsp_alter_stored_procedure + * return: if failed return error code else NO_ERROR + * parser(in/out): parser environment + * statement(in): a statement node + * + * Note: + */ + +int +jsp_alter_stored_procedure (PARSER_CONTEXT *parser, PT_NODE *statement) +{ + int err = NO_ERROR, sp_recompile, save, lang; + PT_NODE *sp_name = NULL, *sp_owner = NULL, *sp_comment = NULL; + const char *name_str = NULL, *owner_str = NULL, *comment_str = NULL, *target_cls = NULL; + char new_name_str[DB_MAX_IDENTIFIER_LENGTH]; + new_name_str[0] = '\0'; + char downcase_owner_name[DB_MAX_USER_LENGTH]; + downcase_owner_name[0] = '\0'; + char unique_name[DB_MAX_IDENTIFIER_LENGTH + 1]; + unique_name[0] = '\0'; + PT_MISC_TYPE type; + SP_TYPE_ENUM real_type; + MOP sp_mop = NULL, new_owner = NULL, owner = NULL, save_user = NULL; + DB_VALUE user_val, sp_type_val, sp_lang_val, target_cls_val; + + assert (statement != NULL); + + CHECK_MODIFICATION_ERROR (); + + if (prm_get_bool_value (PRM_ID_BLOCK_DDL_STATEMENT)) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_BLOCK_DDL_STMT, 0); + return ER_BLOCK_DDL_STMT; + } + + db_make_null (&user_val); + db_make_null (&sp_type_val); + db_make_null (&sp_lang_val); + db_make_null (&target_cls_val); + + type = PT_NODE_SP_TYPE (statement); + sp_name = statement->info.sp.name; + assert (sp_name != NULL); + + sp_owner = statement->info.sp.owner; + sp_recompile = statement->info.sp.recompile; + sp_comment = statement->info.sp.comment; + + assert (sp_owner != NULL || sp_comment != NULL || sp_recompile); + + name_str = sp_name->info.name.original; + assert (name_str != NULL); + + if (sp_owner != NULL) + { + owner_str = sp_owner->info.name.original; + assert (owner_str != NULL); + } + + comment_str = (char *) PT_NODE_SP_COMMENT (statement); + + AU_DISABLE (save); + + /* authentication */ + if (!au_is_dba_group_member (Au_user)) + { + err = ER_AU_DBA_ONLY; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, err, 1, "change stored procedure owner"); + goto error; + } + + /* existence of sp */ + sp_mop = jsp_find_stored_procedure (name_str, DB_AUTH_SELECT); + if (sp_mop == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + /* when changing the owner, all privileges are revoked */ + if (jsp_get_unique_name (sp_mop, unique_name, DB_MAX_IDENTIFIER_LENGTH) == NULL) + { + assert (er_errid () != NO_ERROR); + } + + owner = jsp_get_owner (sp_mop); + if (owner == NULL) + { + err = ER_FAILED; + goto error; + } + + save_user = Au_user; + if (AU_SET_USER (owner) == NO_ERROR) + { + err = au_object_revoke_all_privileges (DB_OBJECT_PROCEDURE, owner, unique_name); + if (err != NO_ERROR) + { + AU_SET_USER (save_user); + goto error; + } + } + + AU_SET_USER (save_user); + + /* existence of new owner */ + if (sp_owner != NULL) + { + new_owner = db_find_user (owner_str); + if (new_owner == NULL) + { + err = ER_OBJ_OBJECT_NOT_FOUND; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, err, 1, owner_str); + goto error; + } + } + + /* check type */ + err = db_get (sp_mop, SP_ATTR_SP_TYPE, &sp_type_val); + if (err != NO_ERROR) + { + goto error; + } + + real_type = (SP_TYPE_ENUM) db_get_int (&sp_type_val); + if (real_type != jsp_map_pt_misc_to_sp_type (type)) + { + err = ER_SP_INVALID_TYPE; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, err, 2, name_str, + real_type == SP_TYPE_FUNCTION ? "FUNCTION" : "PROCEDURE"); + goto error; + } + + /* change _db_stored_procedure */ + if (sp_owner != NULL) + { + /* change the unique_name */ + sm_downcase_name (owner_str, downcase_owner_name, DB_MAX_USER_LENGTH); + sprintf (new_name_str, "%s.%s", downcase_owner_name, sm_remove_qualifier_name (name_str)); + + db_make_string (&user_val, new_name_str); + err = obj_set (sp_mop, SP_ATTR_UNIQUE_NAME, &user_val); + if (err < 0) + { + goto error; + } + pr_clear_value (&user_val); + + /* change the owner */ + db_make_object (&user_val, new_owner); + err = obj_set (sp_mop, SP_ATTR_OWNER, &user_val); + if (err < 0) + { + goto error; + } + pr_clear_value (&user_val); + } + + /* check lang */ + err = db_get (sp_mop, SP_ATTR_LANG, &sp_lang_val); + if (err != NO_ERROR) + { + goto error; + } + + lang = db_get_int (&sp_lang_val); + if (lang == SP_LANG_PLCSQL) + { + if (sp_owner != NULL || sp_recompile == 1) + { + err = db_get (sp_mop, SP_ATTR_TARGET_CLASS, &target_cls_val); + if (err != NO_ERROR) + { + goto error; + } + target_cls = db_get_string (&target_cls_val); + + if (sp_recompile == 1) + { + owner_str = sm_qualifier_name (name_str, downcase_owner_name, DB_MAX_USER_LENGTH); + } + + err = alter_stored_procedure_code (parser, sp_mop, target_cls, owner_str, sp_recompile); + if (err != NO_ERROR) + { + goto error; + } + pr_clear_value (&target_cls_val); + } + pr_clear_value (&sp_lang_val); + } + + /* change the comment */ + if (sp_comment != NULL) + { + db_make_string (&user_val, comment_str); + err = obj_set (sp_mop, SP_ATTR_COMMENT, &user_val); + if (err < 0) + { + goto error; + } + pr_clear_value (&user_val); + } + +error: + + pr_clear_value (&user_val); + pr_clear_value (&sp_type_val); + pr_clear_value (&sp_lang_val); + pr_clear_value (&target_cls_val); + AU_ENABLE (save); + + return err; +} + +/* + * jsp_map_pt_misc_to_sp_type + * return : stored procedure type ( Procedure or Function ) + * pt_enum(in): Misc Types + * + * Note: + */ + +static SP_TYPE_ENUM +jsp_map_pt_misc_to_sp_type (PT_MISC_TYPE pt_enum) +{ + if (pt_enum == PT_SP_PROCEDURE) + { + return SP_TYPE_PROCEDURE; + } + else + { + return SP_TYPE_FUNCTION; + } +} + +/* + * jsp_map_pt_misc_to_sp_mode + * return : stored procedure mode ( input or output or inout ) + * pt_enum(in) : Misc Types + * + * Note: + */ + +static SP_MODE_ENUM +jsp_map_pt_misc_to_sp_mode (PT_MISC_TYPE pt_enum) +{ + if (pt_enum == PT_INPUT || pt_enum == PT_NOPUT) + { + return SP_MODE_IN; + } + else if (pt_enum == PT_OUTPUT) + { + return SP_MODE_OUT; + } + else + { + return SP_MODE_INOUT; + } +} + +static SP_DIRECTIVE_ENUM +jsp_map_pt_to_sp_authid (PT_MISC_TYPE pt_authid) +{ + assert (pt_authid == PT_AUTHID_OWNER || pt_authid == PT_AUTHID_CALLER); + return (pt_authid == PT_AUTHID_OWNER ? SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_OWNER : + SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_CALLER); +} + +/* + * jsp_check_stored_procedure_name - + * return: java stored procedure name + * str(in) : + * + * Note: convert lowercase + */ + +static char * +jsp_check_stored_procedure_name (const char *str) +{ + char buffer[SM_MAX_IDENTIFIER_LENGTH + 2]; + char tmp[SM_MAX_IDENTIFIER_LENGTH + 2]; + char *name = NULL; + static int dbms_output_len = strlen ("dbms_output."); + + + if (strncasecmp (str, "dbms_output.", dbms_output_len) == 0) + { + sprintf (buffer, "public.dbms_output.%s", + sm_downcase_name (str + dbms_output_len, tmp, strlen (str + dbms_output_len) + 1)); + } + else + { + sm_user_specified_name (str, buffer, SM_MAX_IDENTIFIER_LENGTH); + } + + name = strdup (buffer); + + return name; +} + +/* + * drop_stored_procedure - + * return: Error code + * name(in): jsp name + * expected_type(in): + * + * Note: + */ + +static int +drop_stored_procedure (const char *name, SP_TYPE_ENUM expected_type) +{ + MOP sp_mop, arg_mop, owner, save_user; + DB_VALUE sp_type_val, arg_cnt_val, args_val, owner_val, generated_val, target_cls_val, lang_val, temp; + SP_TYPE_ENUM real_type; + std::string class_name; + const char *target_cls; + DB_SET *arg_set_p; + int save, i, arg_cnt, lang; + int err; + char unique_name[DB_MAX_IDENTIFIER_LENGTH + 1]; + unique_name[0] = '\0'; + + AU_DISABLE (save); + + db_make_null (&args_val); + db_make_null (&owner_val); + + sp_mop = jsp_find_stored_procedure (name, DB_AUTH_SELECT); + if (sp_mop == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + err = db_get (sp_mop, SP_ATTR_OWNER, &owner_val); + if (err != NO_ERROR) + { + goto error; + } + owner = db_get_object (&owner_val); + + if (!ws_is_same_object (owner, Au_user) && !au_is_dba_group_member (Au_user)) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_DROP_NOT_ALLOWED_PRIVILEGES, 0); + err = er_errid (); + goto error; + } + + err = db_get (sp_mop, SP_ATTR_IS_SYSTEM_GENERATED, &generated_val); + if (err != NO_ERROR) + { + goto error; + } + + if (1 == db_get_int (&generated_val)) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_DROP_NOT_ALLOWED_SYSTEM_GENERATED, 0); + err = er_errid (); + goto error; + } + + err = db_get (sp_mop, SP_ATTR_SP_TYPE, &sp_type_val); + if (err != NO_ERROR) + { + goto error; + } + + real_type = (SP_TYPE_ENUM) db_get_int (&sp_type_val); + if (real_type != expected_type) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_TYPE, 2, name, + real_type == SP_TYPE_FUNCTION ? "FUNCTION" : "PROCEDURE"); + + err = er_errid (); + goto error; + } + + // delete _db_stored_procedure_code + + err = db_get (sp_mop, SP_ATTR_LANG, &lang_val); + if (err != NO_ERROR) + { + goto error; + } + + lang = db_get_int (&lang_val); + if (lang == SP_LANG_PLCSQL) + { + err = db_get (sp_mop, SP_ATTR_TARGET_CLASS, &target_cls_val); + if (err != NO_ERROR) + { + goto error; + } + + target_cls = db_get_string (&target_cls_val); + err = drop_stored_procedure_code (target_cls); + if (err != NO_ERROR) + { + goto error; + } + } + + err = db_get (sp_mop, SP_ATTR_ARG_COUNT, &arg_cnt_val); + if (err != NO_ERROR) + { + goto error; + } + + arg_cnt = db_get_int (&arg_cnt_val); + + err = db_get (sp_mop, SP_ATTR_ARGS, &args_val); + if (err != NO_ERROR) + { + goto error; + } + + arg_set_p = db_get_set (&args_val); + + for (i = 0; i < arg_cnt; i++) + { + set_get_element (arg_set_p, i, &temp); + arg_mop = db_get_object (&temp); + err = obj_delete (arg_mop); + pr_clear_value (&temp); + if (err != NO_ERROR) + { + goto error; + } + } + + /* before deleting an object, all permissions are revoked. */ + if (jsp_get_unique_name (sp_mop, unique_name, DB_MAX_IDENTIFIER_LENGTH) == NULL) + { + assert (er_errid () != NO_ERROR); + } + + save_user = Au_user; + if (AU_SET_USER (owner) == NO_ERROR) + { + err = au_object_revoke_all_privileges (DB_OBJECT_PROCEDURE, owner, unique_name); + if (err != NO_ERROR) + { + AU_SET_USER (save_user); + goto error; + } + } + + AU_SET_USER (save_user); + + err = au_delete_auth_of_dropping_database_object (DB_OBJECT_PROCEDURE, name); + if (err != NO_ERROR) + { + goto error; + } + + err = obj_delete (sp_mop); + +error: + AU_ENABLE (save); + + pr_clear_value (&args_val); + pr_clear_value (&owner_val); + + return err; +} + +/* + * drop_stored_procedure_code - + * return: Error code + * name(in): jsp name + * + * Note: + */ + +static int +drop_stored_procedure_code (const char *name) +{ + MOP code_mop, owner; + DB_VALUE owner_val, generated_val; + int save; + int err; + + AU_DISABLE (save); + + db_make_null (&owner_val); + + code_mop = jsp_find_stored_procedure_code (name); + if (code_mop == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + err = db_get (code_mop, SP_ATTR_OWNER, &owner_val); + if (err != NO_ERROR) + { + goto error; + } + owner = db_get_object (&owner_val); + + if (!ws_is_same_object (owner, Au_user) && !au_is_dba_group_member (Au_user)) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_DROP_NOT_ALLOWED_PRIVILEGES, 0); + err = er_errid (); + goto error; + } + + err = db_get (code_mop, SP_ATTR_IS_SYSTEM_GENERATED, &generated_val); + if (err != NO_ERROR) + { + goto error; + } + + if (!DB_IS_NULL (&generated_val) && 1 == db_get_int (&generated_val)) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_DROP_NOT_ALLOWED_SYSTEM_GENERATED, 0); + err = er_errid (); + goto error; + } + + // TODO: If a unreloadable SP is deleted, mark a flag in PL server to block calling the deleted SP + err = obj_delete (code_mop); + +error: + AU_ENABLE (save); + + pr_clear_value (&owner_val); + + return err; +} + +/* + * alter_stored_procedure_code - + * return: Error code + * name(in): jsp name + * + * Note: + */ + +static int +alter_stored_procedure_code (PARSER_CONTEXT *parser, MOP sp_mop, const char *name, const char *owner_str, + int sp_recompile) +{ + const char *scode = NULL, *decl = NULL; + int scode_len, save, err; + MOP code_mop; + DB_VALUE scode_val, value; + PLCSQL_COMPILE_REQUEST compile_request; + PLCSQL_COMPILE_RESPONSE compile_response; + SP_INFO sp_info; + SP_CODE_INFO code_info; + DB_OBJECT *object_p; + DB_OTMPL *obt_p = NULL; + + AU_DISABLE (save); + + db_make_null (&scode_val); + db_make_null (&value); + + code_mop = jsp_find_stored_procedure_code (name); + if (code_mop == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + err = db_get (code_mop, SP_ATTR_SOURCE_CODE, &scode_val); + if (err != NO_ERROR) + { + goto error; + } + + scode = db_get_string (&scode_val); + scode_len = db_get_string_size (&scode_val); + + sp_info.owner = db_find_user (owner_str); + + assert (scode && scode_len); + compile_request.code.assign (scode, scode_len); + compile_request.owner.assign (owner_str); + pr_clear_value (&scode_val); + + // TODO: Only the owner's rights is supported for PL/CSQL + au_perform_push_user (sp_info.owner); + err = plcsql_transfer_file (compile_request, compile_response); + au_perform_pop_user (); + + if (err == NO_ERROR && compile_response.err_code == NO_ERROR) + { + decl = compile_response.java_signature.c_str (); + } + else + { + if (err == NO_ERROR && compile_response.err_code == NO_ERROR) + { + decl = compile_response.java_signature.c_str (); + } + else + { + err = ER_SP_COMPILE_ERROR; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_COMPILE_ERROR, 3, compile_response.err_line, + compile_response.err_column, compile_response.err_msg.c_str ()); + pt_record_error (parser, parser->statement_number, compile_response.err_line, compile_response.err_column, er_msg (), + NULL); + goto error; + } + } + + if (decl) + { + std::string target = decl; + sp_split_target_signature (target, sp_info.target_class, sp_info.target_method); + } + + code_info.name = sp_info.target_class; + code_info.ocode = compile_response.compiled_code; + + if (sp_recompile == 1) + { + /* recompile */ + code_info.owner = NULL; + } + else + { + /* owner to */ + code_info.owner = sp_info.owner; + } + + err = sp_edit_stored_procedure_code (code_mop, code_info); + if (err != NO_ERROR) + { + goto error; + } + + /* Update the target_class column in the _db_stored_procedure catalog. */ + obt_p = dbt_edit_object (sp_mop); + if (obt_p == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + db_make_string (&value, code_info.name.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_TARGET_CLASS, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + object_p = dbt_finish_object (obt_p); + if (!object_p) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + obt_p = NULL; + + err = locator_flush_instance (object_p); + if (err != NO_ERROR) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + obj_delete (object_p); + goto error; + } + +error: + AU_ENABLE (save); + + pr_clear_value (&scode_val); + pr_clear_value (&value); + + return err; +} + +/* + * jsp_set_prepare_call - + * return: none + * + * Note: + */ + +void +jsp_set_prepare_call (void) +{ + int depth = tran_get_libcas_depth (); + is_prepare_call[depth] = true; +} + +/* + * jsp_unset_prepare_call - + * return: none + * + * Note: + */ + +void +jsp_unset_prepare_call (void) +{ + int depth = tran_get_libcas_depth (); + is_prepare_call[depth] = false; +} + +/* + * jsp_is_prepare_call - + * return: bool + * + * Note: + */ + +bool +jsp_is_prepare_call () +{ + int depth = tran_get_libcas_depth (); + return is_prepare_call[depth]; +} + +static int +jsp_check_overflow_args (PARSER_CONTEXT *parser, PT_NODE *node, int num_params, int num_args) +{ + if (num_args > num_params) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_PARAM_COUNT, 2, num_params, num_args); + return er_errid (); + } + else if (num_args < num_params) + { + // there are trailing default arguments + return num_params - num_args; + } + return 0; +} + +/* + * pt_to_method_arglist () - converts a parse expression tree list of + * method call arguments to method argument array + * return: A NULL on error occurred + * parser(in): + * target(in): + * node_list(in): should be parse name nodes + * subquery_as_attr_list(in): + */ +static int * +pt_to_method_arglist (PARSER_CONTEXT *parser, PT_NODE *target, PT_NODE *node_list, PT_NODE *subquery_as_attr_list) +{ + int *arg_list = NULL; + int i = 1; + int num_args = pt_length_of_list (node_list) + 1; + PT_NODE *node; + + arg_list = (int *) db_private_alloc (NULL, num_args); + if (!arg_list) + { + return NULL; + } + + if (subquery_as_attr_list != NULL) + { + if (target != NULL) + { + /* the method call target is the first element in the array */ + arg_list[0] = pt_find_attribute (parser, target, subquery_as_attr_list); + if (arg_list[0] == -1) + { + return NULL; + } + } + else + { + i = 0; + } + + for (node = node_list; node != NULL; node = node->next) + { + arg_list[i] = pt_find_attribute (parser, node, subquery_as_attr_list); + if (arg_list[i] == -1) + { + return NULL; + } + i++; + } + } + else + { + for (node = node_list; node != NULL; node = node->next) + { + arg_list[i] = i; + i++; + } + } + + return arg_list; +} + +/* + * jsp_make_pl_signature () - converts a parse expression tree list of pl calls to pl_signature struct + * return: error_code + * parser(in): + * node_list(in): should be parse pl nodes + * subquery_as_attr_list(in): + * sig(out): pl_signature struct + */ +int +jsp_make_pl_signature (PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *subquery_as_attr_list, cubpl::pl_signature &sig) +{ + int save; + int error = NO_ERROR; + char user_name_buffer [DB_MAX_USER_LENGTH + 1]; + + assert (node); + + sp_entry entry (SP_ATTR_INDEX_LAST); + + { + PT_NODE *method_name_node = node->info.method_call.method_name; + const char *name = PT_NAME_RESOLVED (method_name_node) ? parser_print_tree (parser, + method_name_node) : PT_NAME_ORIGINAL (method_name_node); + + sig.name = db_private_strdup (NULL, name); + if (PT_IS_METHOD (node)) + { + sig.type = PT_IS_CLASS_METHOD (node) ? PL_TYPE_CLASS_METHOD : PL_TYPE_INSTANCE_METHOD; + } + else + { + DB_OBJECT *mop_p = jsp_find_stored_procedure (name, DB_AUTH_EXECUTE); + if (mop_p == NULL) + { + error = er_errid (); + assert (error != NO_ERROR); + goto exit; + } + + AU_DISABLE (save); + entry.oid = *WS_OID (mop_p); + + for (int i = 0; i < SP_ATTR_INDEX_LAST; i++) + { + error = obj_get (mop_p, sp_get_entry_name (i).data (), &entry.vals[i]); + if (error != NO_ERROR) + { + goto exit; + } + } + + int lang = db_get_int (&entry.vals[SP_ATTR_INDEX_LANG]); + sig.type = (lang == SP_LANG_PLCSQL) ? PL_TYPE_PLCSQL : PL_TYPE_JAVA_SP; + + /* semantic check */ + int directive = db_get_int (&entry.vals[SP_ATTR_INDEX_DIRECTIVE]); + const char *auth_name = (directive == SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_OWNER ? jsp_get_owner_name ( + name, user_name_buffer, DB_MAX_USER_LENGTH) : au_get_current_user_name ()); + + int result_type = db_get_int (&entry.vals[SP_ATTR_INDEX_RETURN_TYPE]); + error = jsp_check_return_type_supported ((DB_TYPE) result_type); + if (error != NO_ERROR) + { + goto exit; + } + + // args + int num_params = db_get_int (&entry.vals[SP_ATTR_INDEX_ARG_COUNT]); + DB_SET *param_set = db_get_set (&entry.vals[SP_ATTR_INDEX_ARGS]); + error = jsp_make_pl_args (parser, node, num_params, param_set, sig); + if (error != NO_ERROR) + { + goto exit; + } + + sig.auth = db_private_strdup (NULL, auth_name); + sig.result_type = result_type; + if (directive == SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_OWNER) + { + jsp_get_owner_name (name, user_name_buffer, DB_MAX_USER_LENGTH); + sig.auth = db_private_strndup (NULL, user_name_buffer, DB_MAX_USER_LENGTH); + } + else + { + sig.auth = db_private_strdup (NULL, au_get_current_user_name ()); + } + } + + // make pl_ext + if (PT_IS_METHOD (node)) + { + PT_NODE *dt = node->info.method_call.on_call_target->data_type; + /* beware of virtual classes */ + + sig.ext.method.class_name = (dt->info.data_type.virt_object) ? (char *) db_get_class_name ( + dt->info.data_type.virt_object) : (char *) dt->info.data_type.entity->info.name.original; + sig.arg.set_arg_size (pt_length_of_list (node->info.method_call.arg_list) + 1); + sig.ext.method.arg_pos = pt_to_method_arglist (parser, node->info.method_call.on_call_target, + node->info.method_call.arg_list, subquery_as_attr_list); + } + else + { + sig.ext.sp.target_class_name = db_private_strdup (NULL, db_get_string (&entry.vals[SP_ATTR_INDEX_TARGET_CLASS])); + sig.ext.sp.target_method_name = db_private_strdup (NULL, db_get_string (&entry.vals[SP_ATTR_INDEX_TARGET_METHOD])); + if (sig.ext.sp.target_class_name != NULL) + { + MOP code_mop = jsp_find_stored_procedure_code (sig.ext.sp.target_class_name); + if (code_mop) + { + sig.ext.sp.code_oid = *WS_OID (code_mop); + } + else + { + // Java SP + sig.ext.sp.code_oid = OID_INITIALIZER; + } + } + } + } + +exit: + AU_ENABLE (save); + return error; +} + +int +jsp_make_pl_args (PARSER_CONTEXT *parser, PT_NODE *node, int num_params, DB_SET *param_set, cubpl::pl_signature &sig) +{ + int error = NO_ERROR; + + DB_VALUE temp; + db_make_null (&temp); + + { + sig.arg.set_arg_size (num_params); + + // check default arguments + int num_args = pt_length_of_list (node->info.method_call.arg_list); + int num_trailing_default_args = jsp_check_overflow_args (parser, node, num_params, num_args); + if (num_trailing_default_args < 0) + { + error = er_errid (); + goto exit_on_error; + } + + sp_entry entry (SP_ARGS_ATTR_INDEX_LAST); + + for (int i = 0; i < num_params; i++) + { + set_get_element (param_set, i, &temp); + + MOP arg_mop_p = db_get_object (&temp); + if (arg_mop_p == NULL) + { + error = er_errid (); + assert (error != NO_ERROR); + goto exit_on_error; + } + + for (int i = 0; i < SP_ARGS_ATTR_INDEX_LAST; i++) + { + error = obj_get (arg_mop_p, sp_args_get_entry_name (i).data (), &entry.vals[i]); + if (error != NO_ERROR) + { + goto exit_on_error; + } + } + + int arg_mode = db_get_int (&entry.vals[SP_ARGS_ATTR_INDEX_MODE]); + error = jsp_check_out_param_in_query (parser, node, arg_mode); + if (error != NO_ERROR) + { + goto exit_on_error; + } + + int arg_type = db_get_int (&entry.vals[SP_ARGS_ATTR_INDEX_DATA_TYPE]); + error = jsp_check_param_type_supported ((DB_TYPE) arg_type, arg_mode); + if (error != NO_ERROR) + { + goto exit_on_error; + } + + const char *default_value_str = NULL; + int default_value_size = PL_ARG_DEFAULT_NONE; + + int num_required_args = num_params - num_trailing_default_args; + + if (i >= num_required_args) + { + int is_optional = db_get_int (&entry.vals[SP_ARGS_ATTR_INDEX_IS_OPTIONAL]); + if (is_optional == 1) + { + const DB_VALUE &default_val = entry.vals[SP_ARGS_ATTR_INDEX_DEFAULT_VALUE]; + if (!DB_IS_NULL (&default_val)) + { + default_value_size = db_get_string_size (&default_val); // null character + if (default_value_size > 0) + { + default_value_str = db_get_string (&default_val); + } + } + else + { + default_value_size = PL_ARG_DEFAULT_NULL; // special value when default value is *NULL* + } + } + else + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_INVALID_PARAM_COUNT, 2, num_params, num_args); + error = er_errid (); + goto exit_on_error; + } + } + + sig.arg.arg_mode[i] = arg_mode; + sig.arg.arg_type[i] = arg_type; + + sig.arg.arg_default_value_size[i] = default_value_size; + if (default_value_str) + { + sig.arg.arg_default_value[i] = db_private_strndup (NULL, default_value_str, default_value_size); + } + } + } + +exit_on_error: + return error; +} + +static int +check_execute_authorization_by_query (const MOP sp_obj) +{ + int error = NO_ERROR, save; + const char *query = "SELECT [au] FROM " CT_CLASSAUTH_NAME + " [au] WHERE [object_type] = ? and [auth_type] = 'EXECUTE' and [object_of] = ? and [grantee] = ?"; + DB_QUERY_RESULT *result = NULL; + DB_SESSION *session = NULL; + DB_VALUE val[3]; + int stmt_id; + int cnt = 0; + + db_make_null (&val[0]); + db_make_null (&val[1]); + db_make_null (&val[2]); + + /* Disable the checking for internal authorization object access */ + AU_DISABLE (save); + + session = db_open_buffer_local (query); + if (session == NULL) + { + ASSERT_ERROR_AND_SET (error); + goto release; + } + + error = db_set_system_generated_statement (session); + if (error != NO_ERROR) + { + goto release; + } + + stmt_id = db_compile_statement_local (session); + if (stmt_id < 0) + { + ASSERT_ERROR_AND_SET (error); + goto release; + } + + db_make_int (&val[0], (int) DB_OBJECT_PROCEDURE); + db_make_object (&val[1], sp_obj); + db_make_object (&val[2], Au_user); + + error = db_push_values (session, 3, val); + if (error != NO_ERROR) + { + goto release; + } + + cnt = error = db_execute_statement_local (session, stmt_id, &result); + if (error < 0) + { + goto release; + } + + error = db_query_end (result); + +release: + if (session != NULL) + { + db_close_session (session); + } + pr_clear_value (&val[0]); + pr_clear_value (&val[1]); + pr_clear_value (&val[2]); + + AU_ENABLE (save); + + return cnt; +} + +static int +check_execute_authorization (const MOP sp_obj, const DB_AUTH au_type) +{ + int error = NO_ERROR; + MOP owner_mop = NULL; + DB_VALUE owner; + + if (au_type != DB_AUTH_EXECUTE) + { + return NO_ERROR; + } + + if (au_is_dba_group_member (Au_user)) + { + return NO_ERROR; + } + + error = db_get (sp_obj, SP_ATTR_OWNER, &owner); + if (error == NO_ERROR) + { + // check sp's owner is current user + owner_mop = db_get_object (&owner); + if (ws_is_same_object (owner_mop, Au_user) || ws_is_same_object (owner_mop, Au_public_user)) + { + return NO_ERROR; + } + else if (check_execute_authorization_by_query (sp_obj) == 0) + { + error = ER_AU_EXECUTE_FAILURE; + er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0); + } + else + { + error = er_errid (); + } + } + + return error; +} + +PT_NODE * +jsp_get_default_expr_node_list (PARSER_CONTEXT *parser, cubpl::pl_signature &sig) +{ + PT_NODE *default_next_node_list = NULL; + PT_NODE *default_next_node = NULL; + for (int i = 0; i < sig.arg.arg_size; i++) + { + if (sig.arg.arg_default_value_size[i] == 0) + { + default_next_node = pt_make_string_value (parser, NULL); + } + else if (sig.arg.arg_default_value_size[i] > 0) + { + DB_DEFAULT_EXPR default_expr; + pt_get_default_expression_from_string (parser, sig.arg.arg_default_value[i], sig.arg.arg_default_value_size[i], + &default_expr); + + // from pt_resolve_default_value + if (default_expr.default_expr_type != DB_DEFAULT_NONE) + { + PT_OP_TYPE op = pt_op_type_from_default_expr_type (default_expr.default_expr_type); + PT_NODE *default_op_value_node = pt_expression_0 (parser, op); + + if (default_expr.default_expr_op == NULL_DEFAULT_EXPRESSION_OPERATOR) + { + default_next_node = default_op_value_node; + } + else + { + PT_NODE *arg1, *arg2, *arg3; + arg1 = default_op_value_node; + bool has_user_format = default_expr.default_expr_format ? true : false; + arg2 = pt_make_string_value (parser, default_expr.default_expr_format); + + if (arg2 == NULL) + { + parser_free_tree (parser, default_op_value_node); + return NULL; + } + + arg3 = parser_new_node (parser, PT_VALUE); + if (arg3 == NULL) + { + parser_free_tree (parser, default_op_value_node); + parser_free_tree (parser, arg2); + return NULL; + } + + arg3->type_enum = PT_TYPE_INTEGER; + const char *lang_str = prm_get_string_value (PRM_ID_INTL_DATE_LANG); + int flag = 0; + lang_set_flag_from_lang (lang_str, has_user_format, 0, &flag); + arg3->info.value.data_value.i = (long) flag; + + default_next_node = parser_make_expression (parser, PT_TO_CHAR, arg1, arg2, arg3); + if (default_next_node == NULL) + { + parser_free_tree (parser, default_op_value_node); + parser_free_tree (parser, arg2); + parser_free_tree (parser, arg3); + return NULL; + } + } + } + else + { + default_next_node = pt_make_string_value (parser, sig.arg.arg_default_value[i]); + default_next_node = pt_wrap_with_cast_op (parser, default_next_node, pt_db_to_type_enum ((DB_TYPE) sig.arg.arg_type[i]), + TP_FLOATING_PRECISION_VALUE, 0, NULL); + } + } + + if (default_next_node != NULL) + { + default_next_node = pt_semantic_type (parser, default_next_node, NULL); + if (default_next_node == NULL) + { + return NULL; + } + + default_next_node_list = parser_append_node (default_next_node, default_next_node_list); + } + } + + return default_next_node_list; +} diff --git a/src/sp/jsp_cl.h b/src/sp/jsp_cl.h index 9a2a8b4373f..dbf2af8edfb 100644 --- a/src/sp/jsp_cl.h +++ b/src/sp/jsp_cl.h @@ -32,62 +32,43 @@ #error Does not belong to server module. #endif /* SERVER_MODE */ -#include "parse_tree.h" - -#define SP_CLASS_NAME "_db_stored_procedure" -#define SP_ARG_CLASS_NAME "_db_stored_procedure_args" - -#define SP_ATTR_NAME "sp_name" -#define SP_ATTR_SP_TYPE "sp_type" -#define SP_ATTR_RETURN_TYPE "return_type" -#define SP_ATTR_ARGS "args" -#define SP_ATTR_ARG_COUNT "arg_count" -#define SP_ATTR_LANG "lang" -#define SP_ATTR_TARGET "target" -#define SP_ATTR_OWNER "owner" -#define SP_ATTR_COMMENT "comment" - -#define SP_ATTR_ARG_NAME "arg_name" -#define SP_ATTR_INDEX_OF_NAME "index_of" -#define SP_ATTR_DATA_TYPE "data_type" -#define SP_ATTR_MODE "mode" -#define SP_ATTR_ARG_COMMENT "comment" - -typedef enum -{ - SP_TYPE_PROCEDURE = 1, - SP_TYPE_FUNCTION -} SP_TYPE_ENUM; +#ifdef __cplusplus +#include +#include +#endif -typedef enum -{ - SP_MODE_IN = 1, - SP_MODE_OUT, - SP_MODE_INOUT -} SP_MODE_ENUM; - -typedef enum -{ - SP_LANG_PLCSQL = 0, - SP_LANG_JAVA = 1 -} SP_LANG_ENUM; +#include "parse_tree.h" +#include "sp_constants.hpp" +#include "pl_signature.hpp" extern int jsp_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * statement); extern int jsp_alter_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * statement); extern int jsp_drop_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * statement); extern int jsp_call_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * statement); -extern int jsp_check_out_param_in_query (PARSER_CONTEXT * parser, PT_NODE * node, int arg_mode); -extern int jsp_check_param_type_supported (PT_NODE * node); extern int jsp_check_return_type_supported (DB_TYPE type); +extern int jsp_make_pl_signature (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE * subquery_as_attr_list, + cubpl::pl_signature & signature); +extern int jsp_make_pl_args (PARSER_CONTEXT * parser, PT_NODE * node, int num_params, DB_SET * param_set, + cubpl::pl_signature & signature); + extern int jsp_is_exist_stored_procedure (const char *name); + +extern char *jsp_get_owner_name (const char *name, char *buf, int buf_size); extern int jsp_get_return_type (const char *name); extern int jsp_get_sp_type (const char *name); -extern MOP jsp_find_stored_procedure (const char *name); +extern MOP jsp_find_stored_procedure (const char *name, DB_AUTH purpose); +extern MOP jsp_find_stored_procedure_code (const char *name); +extern int jsp_find_sp_of_another_owner (const char *name, MOP * return_mop); + +extern MOP jsp_get_owner (MOP mop_p); +extern char *jsp_get_name (MOP mop_p); +extern char *jsp_get_unique_name (MOP mop_p, char *buf, int buf_size); extern void jsp_set_prepare_call (void); extern void jsp_unset_prepare_call (void); extern bool jsp_is_prepare_call (void); +extern PT_NODE *jsp_get_default_expr_node_list (PARSER_CONTEXT * parser, cubpl::pl_signature & sig); #endif /* _JSP_CL_H_ */ diff --git a/src/sp/jsp_file.h b/src/sp/jsp_file.h deleted file mode 100644 index 883c050ada7..00000000000 --- a/src/sp/jsp_file.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2008 Search Solution Corporation - * Copyright 2016 CUBRID Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -/* - * jsp_file.h - Functions to manage files related to Java Stored Procedure Server - * - * Note: - */ - -#ifndef _JSP_FILE_H_ -#define _JSP_FILE_H_ - -#ident "$Id$" - -#include "porting.h" -#include - -typedef struct javasp_server_info JAVASP_SERVER_INFO; -struct javasp_server_info -{ - int pid; - int port; -}; - -#define JAVASP_PID_DISABLED -1 -#define JAVASP_PORT_DISABLED -2 -#define JAVASP_PORT_UDS_MODE -1 - -#define JAVASP_SERVER_INFO_INITIALIZER \ - {JAVASP_PID_DISABLED, JAVASP_PORT_DISABLED} - -#ifdef __cplusplus -extern "C" -{ -#endif - - extern bool javasp_open_info_dir (); - extern FILE *javasp_open_info (const char *db_name, const char *mode); - extern void javasp_unlink_info (const char *db_name); - - extern bool javasp_read_info (const char *db_name, JAVASP_SERVER_INFO & info); - extern bool javasp_write_info (const char *db_name, JAVASP_SERVER_INFO info); - extern bool javasp_reset_info (const char *db_name); - - extern bool javasp_get_info_file (char *buf, size_t len, const char *db_name); - extern bool javasp_get_error_file (char *buf, size_t len, const char *db_name); - extern bool javasp_get_log_file (char *buf, size_t len, const char *db_name); - -#ifdef __cplusplus -} -#endif - -#endif /* _JSP_FILE_H_ */ diff --git a/src/sp/method_invoke_group.cpp b/src/sp/method_invoke_group.cpp new file mode 100644 index 00000000000..1c6ebe71e84 --- /dev/null +++ b/src/sp/method_invoke_group.cpp @@ -0,0 +1,253 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "method_invoke_group.hpp" + +#include "boot_sr.h" +#include "dbtype.h" /* db_value_* */ +#include "db_value_printer.hpp" +#include "pl_comm.h" /* common communcation functions for javasp */ +#include "mem_block.hpp" /* cubmem::extensible_block */ + +#include "method_struct_invoke.hpp" +#include "object_primitive.h" +#include "object_representation.h" /* OR_ */ +#include "packer.hpp" +#include "pl_connection.hpp" +#include "session.h" +#include "string_buffer.hpp" +#include "pl_session.hpp" +#include "network_callback_sr.hpp" + +#if defined (SA_MODE) +#include "query_method.hpp" +#endif +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" + +namespace cubmethod +{ +////////////////////////////////////////////////////////////////////////// +// Method Group to invoke together +////////////////////////////////////////////////////////////////////////// + method_invoke_group::method_invoke_group (cubpl::pl_signature_array &sig_array) + : m_id ((std::uint64_t) this) + , m_stack (nullptr) + , m_sig_array (sig_array) + { + assert (sig_array.num_sigs > 0); + + // assert +#if !defined (NDEBUG) + for (int i = 0; i < sig_array.num_sigs; i++) + { + assert (PL_TYPE_IS_METHOD (sig_array.sigs[i].type)); + } +#endif + + DB_VALUE v; + db_make_null (&v); + m_result_vector.resize (sig_array.num_sigs, v); + } + + method_invoke_group::~method_invoke_group () + { + destroy_resources (); + } + + DB_VALUE & + method_invoke_group::get_return_value (int index) + { + assert (index >= 0 && index < (int) m_sig_array.num_sigs); + return m_result_vector[index]; + } + + METHOD_GROUP_ID + method_invoke_group::get_id () const + { + return m_id; + } + + bool + method_invoke_group::is_running () const + { + return m_is_running; + } + + int + method_invoke_group::prepare (std::vector> &arg_base) + { + int error = NO_ERROR; + + SESSION_ID s_id = cubpl::get_session ()->get_id (); + int req_id = m_stack->get_and_increment_request_id (); + TRANID t_id = m_stack->get_tran_id (); + + cubmethod::header header (s_id, METHOD_REQUEST_ARG_PREPARE, req_id); + cubmethod::prepare_args arg (m_id, t_id, METHOD_TYPE_CLASS_METHOD, arg_base); // TOD + + error = xs_callback_send_args (m_stack->get_thread_entry (), header, arg); + return error; + } + + int method_invoke_group::execute (std::vector> &arg_base) + { + int error = NO_ERROR; + SESSION_ID s_id; + TRANID t_id; + + m_stack = cubpl::get_session ()->create_and_push_stack (nullptr); + s_id = cubpl::get_session ()->get_id (); + t_id = m_stack->get_tran_id (); + + // prepare args + error = prepare (arg_base); + if (error != NO_ERROR) + { + goto exit; + } + + for (int i = 0; i < m_sig_array.num_sigs; i++) + { + int req_id = m_stack->get_and_increment_request_id (); + // invoke + cubmethod::header header (s_id, METHOD_REQUEST_INVOKE /* default */, 0); + error = xs_callback_send_args (m_stack->get_thread_entry (), header, m_id, m_sig_array.sigs[i]); + if (error != NO_ERROR) + { + break; + } + + DB_VALUE &result = m_result_vector[i]; + db_value_clear (&result); + + auto get_method_result = [&] (cubmem::block & b) + { + int e = NO_ERROR; + packing_unpacker unpacker (b); + int status; + unpacker.unpack_int (status); + if (status == METHOD_SUCCESS) + { + unpacker.unpack_db_value (result); + } + else + { + unpacker.unpack_int (e); /* er_errid */ + } + return e; + }; + + // get_return + error = xs_callback_receive (m_stack->get_thread_entry (), get_method_result); + if (error != NO_ERROR) + { + break; + } + +#if 0 // TODO + if (m_session->is_interrupted ()) + { + error = m_session->get_interrupt_id (); + } + + if (error != NO_ERROR) + { + // if error is not interrupt reason, interrupt is not set + m_session->set_interrupt (error, (er_has_error () && er_msg ()) ? er_msg () : ""); + break; + } +#endif + } + + if (m_stack) + { + delete m_stack; + } +exit: + return error; + } + + void + method_invoke_group::begin () + { + if (m_is_running == true) + { + return; + } + + m_is_running = true; + } + + int method_invoke_group::reset (bool is_end_query) + { + int error = NO_ERROR; + +// TODO +#if 0 + if (!is_end_query) + { + cubmethod::header header (get_session_id(), METHOD_REQUEST_END, get_and_increment_request_id ()); + std::vector handler_vec (m_handler_set.begin (), m_handler_set.end ()); + error = xs_callback_send_args (m_thread_p, header, handler_vec); + m_handler_set.clear (); + } + +#endif + + return error; + } + + void + method_invoke_group::destroy_resources () + { + pr_clear_value_vector (m_result_vector); + } + + void + method_invoke_group::end () + { + if (m_is_running == false) + { + return; + } + + // FIXME + // m_rctx->pop_stack (m_thread_p, this); + + m_is_running = false; + } + + int + method_invoke_group::get_num_methods () + { + return m_sig_array.num_sigs; + } + + std::string + method_invoke_group::get_error_msg () + { + return m_err_msg; + } + + void + method_invoke_group::set_error_msg (const std::string &msg) + { + m_err_msg = msg; + } +} // namespace cubmethod diff --git a/src/method/method_invoke_group.hpp b/src/sp/method_invoke_group.hpp similarity index 60% rename from src/method/method_invoke_group.hpp rename to src/sp/method_invoke_group.hpp index e9c59cbf3b9..d8dde326502 100644 --- a/src/method/method_invoke_group.hpp +++ b/src/sp/method_invoke_group.hpp @@ -37,14 +37,17 @@ #include #include -#include "method_connection_pool.hpp" /* cubmethod::connection */ -#include "method_def.hpp" /* method_sig_node */ -#include "method_runtime_context.hpp" /* cubmethod::runtime_context */ +#include "pl_connection.hpp" /* cubpl::connection */ + #include "method_struct_parameter_info.hpp" /* db_parameter_info */ #include "mem_block.hpp" /* cubmem::block, cubmem::extensible_block */ #include "porting.h" /* SOCKET */ #include "storage_common.h" +#include "pl_execution_stack_context.hpp" +#include "pl_signature.hpp" +#include "pl_session.hpp" + // thread_entry.hpp namespace cubthread { @@ -56,6 +59,7 @@ namespace cubmethod ////////////////////////////////////////////////////////////////////////// // Method Group to invoke together ////////////////////////////////////////////////////////////////////////// + // forward declarations class method_invoke; @@ -63,7 +67,7 @@ namespace cubmethod { public: method_invoke_group () = delete; // Not DefaultConstructible - method_invoke_group (cubthread::entry *thread_p, const method_sig_list &sigs, bool is_for_scan); + method_invoke_group (cubpl::pl_signature_array &sig); method_invoke_group (method_invoke_group &&other) = delete; // Not MoveConstructible method_invoke_group (const method_invoke_group ©) = delete; // Not CopyConstructible @@ -74,76 +78,33 @@ namespace cubmethod ~method_invoke_group (); void begin (); - int prepare (std::vector> &arg_base, const std::vector &arg_use_vec); + int prepare (std::vector> &arg_base); int execute (std::vector> &arg_base); int reset (bool is_end_query); - void destroy_resources (); void end (); + int get_num_methods (); DB_VALUE &get_return_value (int index); - int get_num_methods () const; METHOD_GROUP_ID get_id () const; - SOCKET get_socket () const; - cubthread::entry *get_thread_entry () const; std::queue &get_data_queue (); - cubmethod::runtime_context *get_runtime_context (); - connection_pool &get_connection_pool (); - SESSION_ID get_session_id () const - { - return m_sid; - } - TRANID get_tran_id (); bool is_running () const; - bool is_for_scan () const; - - // cursor interface for method_invoke - query_cursor *create_cursor (QUERY_ID query_id, bool oid_included); - query_cursor *get_cursor (QUERY_ID query_id); - void register_returning_cursor (QUERY_ID query_id); - void deregister_returning_cursor (QUERY_ID query_id); - - // client handelr - void register_client_handler (int handler_id); // error std::string get_error_msg (); void set_error_msg (const std::string &msg); - db_parameter_info *get_db_parameter_info () const; - - void set_db_parameter_info (db_parameter_info *param_info); - inline METHOD_REQ_ID get_and_increment_request_id () - { - return m_rctx->get_and_increment_request_id(); - } + void destroy_resources (); private: - void destory_all_cursors (); - - bool is_supported_dbtype (const DB_VALUE &value); - - runtime_context *m_rctx; bool m_is_running; - bool m_is_for_scan; - - connection *m_connection; - std::queue m_data_queue; - - std::unordered_set m_cursor_set; - std::unordered_set m_handler_set; std::string m_err_msg; - SESSION_ID m_sid; METHOD_GROUP_ID m_id; - TRANID m_tid; - - db_parameter_info *m_parameter_info; - cubthread::entry *m_thread_p; - std::set m_kind_type; - std::vector m_method_vector; + cubpl::execution_stack *m_stack; + cubpl::pl_signature_array &m_sig_array; std::vector m_result_vector; /* placeholder for result value */ }; diff --git a/src/sp/jsp_comm.c b/src/sp/pl_comm.c similarity index 88% rename from src/sp/jsp_comm.c rename to src/sp/pl_comm.c index bf89b126fed..c3661954de4 100644 --- a/src/sp/jsp_comm.c +++ b/src/sp/pl_comm.c @@ -18,12 +18,12 @@ /* - * jsp_comm.c - Functions to communicate with Java Stored Procedure Server + * pl_comm.c - Functions to communicate with Java Stored Procedure Server * * Note: */ -#include "jsp_comm.h" +#include "pl_comm.h" #include "config.h" @@ -45,7 +45,7 @@ #include #endif /* not WINDOWS */ -#include "jsp_file.h" +#include "pl_file.h" #include "connection_support.h" #include "porting.h" #include "error_manager.h" @@ -63,12 +63,12 @@ // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" -static SOCKET jsp_connect_server_tcp (int server_port); +static SOCKET pl_connect_server_tcp (int server_port); #if !defined (WINDOWS) -static SOCKET jsp_connect_server_uds (const char *db_name); +static SOCKET pl_connect_server_uds (const char *db_name); #endif /* - * jsp_connect_server + * pl_connect_server * return: connect fail - return Error Code * connection success - return socket fd * @@ -76,26 +76,26 @@ static SOCKET jsp_connect_server_uds (const char *db_name); */ SOCKET -jsp_connect_server (const char *db_name, int server_port) +pl_connect_server (const char *db_name, int server_port) { SOCKET socket = INVALID_SOCKET; #if defined (WINDOWS) - socket = jsp_connect_server_tcp (server_port); + socket = pl_connect_server_tcp (server_port); #else - if (server_port == JAVASP_PORT_UDS_MODE) + if (server_port == PL_PORT_UDS_MODE) { - socket = jsp_connect_server_uds (db_name); + socket = pl_connect_server_uds (db_name); } else { - socket = jsp_connect_server_tcp (server_port); + socket = pl_connect_server_tcp (server_port); } #endif return socket; } /* - * jsp_disconnect_server - + * pl_disconnect_server - * return: none * sockfd(in) : close connection * @@ -103,7 +103,7 @@ jsp_connect_server (const char *db_name, int server_port) */ void -jsp_disconnect_server (SOCKET & sockfd) +pl_disconnect_server (SOCKET & sockfd) { if (!IS_INVALID_SOCKET (sockfd)) { @@ -122,7 +122,7 @@ jsp_disconnect_server (SOCKET & sockfd) } /* - * jsp_writen + * pl_writen * return: fail return -1, * fd(in): Specifies the socket file descriptor. * vptr(in): Points to the buffer containing the message to send. @@ -132,7 +132,7 @@ jsp_disconnect_server (SOCKET & sockfd) */ int -jsp_writen (SOCKET fd, const void *vptr, int n) +pl_writen (SOCKET fd, const void *vptr, int n) { int nwritten; int nleft = n; @@ -170,7 +170,7 @@ jsp_writen (SOCKET fd, const void *vptr, int n) } /* - * jsp_readn + * pl_readn * return: read size * fd(in): Specifies the socket file descriptor. * vptr(in/out): Points to a buffer where the message should be stored. @@ -181,20 +181,20 @@ jsp_writen (SOCKET fd, const void *vptr, int n) */ int -jsp_readn (SOCKET fd, void *vptr, int n) +pl_readn (SOCKET fd, void *vptr, int n) { const static int PING_TIMEOUT = 5000; return css_readn (fd, (char *) vptr, n, PING_TIMEOUT); } int -jsp_readn_with_timeout (SOCKET fd, void *vptr, int n, int timeout) +pl_readn_with_timeout (SOCKET fd, void *vptr, int n, int timeout) { return css_readn (fd, (char *) vptr, n, timeout); } int -jsp_ping (SOCKET fd) +pl_ping (SOCKET fd) { char buffer[DB_MAX_IDENTIFIER_LENGTH]; @@ -203,21 +203,21 @@ jsp_ping (SOCKET fd) char *ptr = or_pack_int (request, OR_INT_SIZE); ptr = or_pack_int (ptr, SP_CODE_UTIL_PING); - int nbytes = jsp_writen (fd, request, OR_INT_SIZE * 2); + int nbytes = pl_writen (fd, request, OR_INT_SIZE * 2); if (nbytes != OR_INT_SIZE * 2) { return ER_SP_NETWORK_ERROR; } int res_size = 0; - nbytes = jsp_readn (fd, (char *) &res_size, OR_INT_SIZE); + nbytes = pl_readn (fd, (char *) &res_size, OR_INT_SIZE); if (nbytes != OR_INT_SIZE) { return ER_SP_NETWORK_ERROR; } res_size = ntohl (res_size); - nbytes = jsp_readn (fd, buffer, res_size); + nbytes = pl_readn (fd, buffer, res_size); if (nbytes != res_size) { return ER_SP_NETWORK_ERROR; @@ -227,7 +227,7 @@ jsp_ping (SOCKET fd) } char * -jsp_get_socket_file_path (const char *db_name) +pl_get_socket_file_path (const char *db_name) { static char path[PATH_MAX]; static bool need_init = true; @@ -255,7 +255,7 @@ jsp_get_socket_file_path (const char *db_name) #if !defined (WINDOWS) static SOCKET -jsp_connect_server_uds (const char *db_name) +pl_connect_server_uds (const char *db_name) { struct sockaddr_un sock_addr; SOCKET sockfd = INVALID_SOCKET; @@ -269,7 +269,7 @@ jsp_connect_server_uds (const char *db_name) int slen = sizeof (sock_addr); memset (&sock_addr, 0, slen); sock_addr.sun_family = AF_UNIX; - snprintf (sock_addr.sun_path, sizeof (sock_addr.sun_path), "%s", jsp_get_socket_file_path (db_name)); + snprintf (sock_addr.sun_path, sizeof (sock_addr.sun_path), "%s", pl_get_socket_file_path (db_name)); int success = connect (sockfd, (struct sockaddr *) &sock_addr, slen); if (success < 0) @@ -285,7 +285,7 @@ jsp_connect_server_uds (const char *db_name) #endif static SOCKET -jsp_connect_server_tcp (int server_port) +pl_connect_server_tcp (int server_port) { struct sockaddr_in tcp_srv_addr; diff --git a/src/sp/jsp_comm.h b/src/sp/pl_comm.h similarity index 71% rename from src/sp/jsp_comm.h rename to src/sp/pl_comm.h index 91f50a5ed2d..730825a21b2 100644 --- a/src/sp/jsp_comm.h +++ b/src/sp/pl_comm.h @@ -18,13 +18,13 @@ /* - * jsp_comm.h - Functions to communicate with Java Stored Procedure Server + * pl_comm.h - Functions to communicate with Java Stored Procedure Server * * Note: */ -#ifndef _JSP_COMM_H_ -#define _JSP_COMM_H_ +#ifndef _PL_COMM_H_ +#define _PL_COMM_H_ #ident "$Id$" @@ -52,14 +52,15 @@ typedef enum SP_CODE_COMPILE = 0x80, + SP_CODE_UTIL_BOOTSTRAP = 0xDD, SP_CODE_UTIL_PING = 0xDE, SP_CODE_UTIL_STATUS = 0xEE, SP_CODE_UTIL_TERMINATE_THREAD = 0xFE, SP_CODE_UTIL_TERMINATE_SERVER = 0xFF } SP_CODE; -typedef struct javasp_status_info JAVASP_STATUS_INFO; -struct javasp_status_info +typedef struct pl_status_info PL_STATUS_INFO; +struct pl_status_info { int pid; int port; @@ -73,14 +74,14 @@ struct javasp_status_info extern "C" { #endif - EXPORT_IMPORT SOCKET jsp_connect_server (const char *db_name, int server_port); - EXPORT_IMPORT void jsp_disconnect_server (SOCKET & sockfd); - EXPORT_IMPORT int jsp_writen (SOCKET fd, const void *vptr, int n); - EXPORT_IMPORT int jsp_readn (SOCKET fd, void *vptr, int n); - EXPORT_IMPORT int jsp_readn_with_timeout (SOCKET fd, void *vptr, int n, int timeout); + EXPORT_IMPORT SOCKET pl_connect_server (const char *db_name, int server_port); + EXPORT_IMPORT void pl_disconnect_server (SOCKET & sockfd); + EXPORT_IMPORT int pl_writen (SOCKET fd, const void *vptr, int n); + EXPORT_IMPORT int pl_readn (SOCKET fd, void *vptr, int n); + EXPORT_IMPORT int pl_readn_with_timeout (SOCKET fd, void *vptr, int n, int timeout); - int jsp_ping (SOCKET fd); - char *jsp_get_socket_file_path (const char *db_name); + int pl_ping (SOCKET fd); + char *pl_get_socket_file_path (const char *db_name); #if defined(WINDOWS) extern int windows_socket_startup (FARPROC hook); @@ -91,4 +92,4 @@ extern "C" } #endif -#endif /* _JSP_COMM_H_ */ +#endif /* _pl_COMM_H_ */ diff --git a/src/sp/pl_compile_handler.cpp b/src/sp/pl_compile_handler.cpp new file mode 100644 index 00000000000..f250963b18a --- /dev/null +++ b/src/sp/pl_compile_handler.cpp @@ -0,0 +1,162 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "pl_compile_handler.hpp" + +#include + +#include "pl_comm.h" +#include "pl_execution_stack_context.hpp" + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" + +namespace cubpl +{ + compile_handler::compile_handler () + { + m_stack = get_session ()->create_and_push_stack (nullptr); + } + + compile_handler::~compile_handler () + { + // exit stack + if (m_stack != nullptr) + { + delete m_stack; + } + } + + int + compile_handler::read_request (cubmem::block &response_blk, int &code) + { + int error_code = m_stack->read_data_from_java (response_blk); + if (error_code != NO_ERROR || response_blk.dim == 0) + { + return ER_FAILED; + } + + cubpacking::unpacker unpacker (response_blk); + if (!response_blk.is_valid ()) + { + error_code = ER_SP_NETWORK_ERROR; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 1, sizeof (int)); + } + else + { + unpacker.unpack_int (code); + (void) m_stack->read_payload_block (unpacker); + } + + return error_code; + } + + void + compile_handler::create_error_response (cubmem::extensible_block &res, int error_code) + { + compile_response compile_response; + compile_response.err_code = (er_errid () != NO_ERROR) ? er_errid () : error_code; + compile_response.err_msg = er_msg ()? er_msg () : "unknown error"; + compile_response.err_line = -1; + compile_response.err_column = -1; + + packing_packer packer; + cubmem::extensible_block eb; + packer.set_buffer_and_pack_all (res, compile_response); + } + + int + compile_handler::compile (const compile_request &req, cubmem::extensible_block &out_blk) + { + int error_code = NO_ERROR; + SESSION_ID sid = get_session ()->get_id (); + + m_stack->set_command (SP_CODE_COMPILE); + error_code = m_stack->send_data_to_java (req); + if (error_code != NO_ERROR) + { + return error_code; + } + + auto bypass_block = [&] (const cubmem::block & b) + { + return m_stack->send_data_to_java (b); + }; + + int code; + cubmem::block response_blk; + do + { + error_code = read_request (response_blk, code); + + cubmem::block &payload_blk = m_stack->get_data_queue().front (); + + if (code == METHOD_REQUEST_COMPILE) + { + if (payload_blk.dim > 0) + { + out_blk.extend_to (payload_blk.dim); + std::memcpy (out_blk.get_ptr (), payload_blk.ptr, payload_blk.dim); + } + else + { + create_error_response (out_blk, error_code); + } + } + else if (code == METHOD_REQUEST_SQL_SEMANTICS) + { + packing_unpacker respone_unpacker (payload_blk); + sql_semantics_request request; + respone_unpacker.unpack_all (request); + + error_code = m_stack->send_data_to_client (bypass_block, request); + } + else if (code == METHOD_REQUEST_GLOBAL_SEMANTICS) + { + packing_unpacker respone_unpacker (payload_blk); + global_semantics_request request; + respone_unpacker.unpack_all (request); + + error_code = m_stack->send_data_to_client (bypass_block, request); + } + else + { + error_code = ER_FAILED; + assert (false); + } + + if (m_stack->get_data_queue ().empty() == false) + { + m_stack->get_data_queue ().pop (); + } + + // free phase + if (response_blk.is_valid ()) + { + delete [] response_blk.ptr; + response_blk.ptr = NULL; + response_blk.dim = 0; + } + } + while (error_code == NO_ERROR && code != METHOD_REQUEST_COMPILE); + +exit: + + return error_code; + } +} \ No newline at end of file diff --git a/src/sp/pl_compile_handler.hpp b/src/sp/pl_compile_handler.hpp new file mode 100644 index 00000000000..d5850833c9e --- /dev/null +++ b/src/sp/pl_compile_handler.hpp @@ -0,0 +1,58 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * pl_compile_handler.hpp + */ + +#ifndef _PL_COMPILE_HANDLER_HPP_ +#define _PL_COMPILE_HANDLER_HPP_ + +#if !defined (SERVER_MODE) && !defined (SA_MODE) +#error Belongs to server module +#endif /* !defined (SERVER_MODE) && !defined (SA_MODE) */ + +#include "pl_execution_stack_context.hpp" +#include "pl_signature.hpp" +#include "pl_session.hpp" + +#include "pl_struct_compile.hpp" + +// forward definitions +struct regu_variable_list_node; + +namespace cubpl +{ + class EXPORT_IMPORT compile_handler + { + public: + compile_handler (); + ~compile_handler (); + + int compile (const compile_request &req, cubmem::extensible_block &out_blk); + + private: + int read_request (cubmem::block &response_blk, int &code); + + void create_error_response (cubmem::extensible_block &res, int error_code); + + execution_stack *m_stack; + }; +} + +#endif // _PL_COMPILE_HANDLER_HPP_ \ No newline at end of file diff --git a/src/sp/pl_connection.cpp b/src/sp/pl_connection.cpp new file mode 100644 index 00000000000..d3bace1c850 --- /dev/null +++ b/src/sp/pl_connection.cpp @@ -0,0 +1,405 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "pl_connection.hpp" + +#include /* std::count_if */ +#include /* std::unique_ptr */ + +#include "boot_sr.h" +#include "pl_sr.h" /* pl_server_port(), pl_connect_server() */ +#include "pl_comm.h" /* pl_disconnect_server (), pl_ping () */ +#include "object_representation.h" /* OR_ */ + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" + +namespace cubpl +{ + ////////////////////////////////////////////////////////////////////////// + // Definitions + ////////////////////////////////////////////////////////////////////////// + + /********************************************************************* + * connection_pool - definition + *********************************************************************/ + + constexpr int SYSTEM_REVISION = -1; + constexpr int INITIAL_REVISION = 0; + + connection_pool::connection_pool (int pool_size) + : m_pool (pool_size, nullptr) + , m_epoch (INITIAL_REVISION) + , m_queue () + , m_mutex () + { + assert (pool_size > 0); + // TODO: make it configurable + m_min_conn_size = 3; + m_inc_conn_size = 5; + + initialize_pool (); + } + + connection_pool::connection_pool (int pool_size, const std::string &db_name, int pl_port, bool is_for_sys) + : connection_pool (pool_size) + { + m_db_name = db_name; + m_db_port = pl_port; + if (is_for_sys) + { + m_epoch = SYSTEM_REVISION; + } + } + + connection_pool::~connection_pool () + { + cleanup_pool (); + } + + connection_view + connection_pool::claim () + { + if (!is_system_pool ()) + { + pl_server_wait_for_ready (); + } + if (m_db_port == PL_PORT_DISABLED) + { + m_db_port = pl_server_port_from_info (); + } + + std::lock_guard lock (m_mutex); + + // Check if a connection is available in the queue + if (!m_queue.empty()) + { + int index = m_queue.front(); + m_queue.pop(); + + if (m_pool[index] == nullptr) + { + create_new_connection (index); + } + + return get_connection_view (index); + } + + // If no connections are available, find a slot for a new connection + for (size_t i = 0; i < m_pool.size(); ++i) + { + if (m_pool[i] == nullptr) + { + create_new_connection (i); + return get_connection_view (i); + } + } + + return nullptr; + } + + void + connection_pool::increment_epoch () + { + if (!is_system_pool ()) + { + m_epoch++; + } + } + + int + connection_pool::get_pool_size () const + { + return m_pool.size (); + } + + int + connection_pool::get_epoch () const + { + return m_epoch; + } + + const char * + connection_pool::get_db_name () const + { + return m_db_name.c_str(); + } + + int + connection_pool::get_db_port () const + { + return m_db_port; + } + + bool + connection_pool::is_system_pool () const + { + return (m_epoch.load (std::memory_order::memory_order_relaxed) == SYSTEM_REVISION); + } + + // private + void + connection_pool::retire (connection *conn) + { + std::lock_guard lock (m_mutex); + + m_queue.push (conn->get_index ()); + } + + void + connection_pool::initialize_pool() + { + for (int i = 0; i < m_min_conn_size && i < m_pool.size (); ++i) + { + m_queue.push (i); // Pre-fill the queue with indices + } + } + + void + connection_pool::cleanup_pool() + { + std::lock_guard lock (m_mutex); + + for (connection *&conn : m_pool) + { + if (conn) + { + delete conn; + conn = nullptr; + } + } + + m_pool.clear(); + while (!m_queue.empty()) + { + m_queue.pop(); + } + } + + void + connection_pool::create_new_connection (int index) + { + connection *conn = new connection (this, index); + m_pool[index] = conn; + } + + connection_view + connection_pool::get_connection_view (int index) + { + connection *conn = m_pool[index]; + return connection_view (conn, [this] (connection *c) + { + if (c) + { + this->retire (c); // Automatically return connection to the pool + } + }); + } + + /********************************************************************* + * connection - definition + *********************************************************************/ + connection::connection (connection_pool *pool, int index) + : m_pool (pool) + , m_index (index) + , m_socket (INVALID_SOCKET) + , m_epoch (pool->get_epoch ()) + { + // + do_reconnect (); + } + + connection::~connection () + { + if (m_socket != INVALID_SOCKET) + { + pl_disconnect_server (m_socket); + } + } + + bool + connection::is_connected () const + { + return m_socket != INVALID_SOCKET; + } + + bool + connection::is_valid () const + { + return (m_socket != INVALID_SOCKET) && (m_pool->get_epoch () == m_epoch || m_pool->get_epoch () == SYSTEM_REVISION); + } + + int + connection::get_index () const + { + return m_index; + } + + SOCKET + connection::get_socket () const + { + return m_socket; + } + + int + connection::send_buffer (const cubmem::block &blk) + { + if (!is_valid ()) + { + do_reconnect (); + } + + OR_ALIGNED_BUF (OR_INT_SIZE) a_request; + char *request = OR_ALIGNED_BUF_START (a_request); + + int request_size = static_cast (blk.dim); + or_pack_int (request, request_size); + + int nbytes = pl_writen (m_socket, request, OR_INT_SIZE); + if (nbytes != OR_INT_SIZE) + { + return do_handle_network_error (nbytes); + } + + nbytes = pl_writen (m_socket, blk.ptr, blk.dim); + if (nbytes != static_cast (blk.dim)) + { + return do_handle_network_error (nbytes); + } + + return NO_ERROR; + } + + int + connection::receive_buffer (cubmem::block &b) + { + return receive_buffer (b, nullptr, -1); + } + + int + connection::receive_buffer (cubmem::block &b, const pl_callback_func *interrupt_func, int timeout_ms) + { + if (!is_valid ()) + { + return do_handle_network_error (-1); + } + + int res_size = 0; + int nbytes; + int elapsed = 0; + + /* read data length */ + while (true) + { + nbytes = pl_readn_with_timeout (m_socket, (char *)&res_size, OR_INT_SIZE, timeout_ms); + if (nbytes < 0) + { + if (errno == ETIMEDOUT) + { + if (interrupt_func && (*interrupt_func)() != NO_ERROR) + { + return er_errid (); + } + continue; + } + return do_handle_network_error (-1); + } + if (nbytes != sizeof (int)) + { + return do_handle_network_error (nbytes); + } + else + { + break; + } + } + + res_size = ntohl (res_size); + + // To avoid invalid res_size is returned by PL server, and to prevent memory exhaustion of cub_server + constexpr int MAX_BUFFER_SIZE = 10 * 1024 * 1024; // 10MB max size + if (res_size > MAX_BUFFER_SIZE || res_size < 0) + { + return do_handle_network_error (nbytes); + } + + if (res_size == 0) + { + // No payload to read + return NO_ERROR; + } + + // Step 3: Extend block to fit the incoming data + cubmem::extensible_block ext_blk; + ext_blk.extend_to (res_size); + + // Step 4: Read the actual data with optional interrupt handling + int total_read = 0; + while (total_read < res_size) + { + nbytes = pl_readn_with_timeout (m_socket, ext_blk.get_ptr() + total_read, res_size - total_read, timeout_ms); + if (errno == ETIMEDOUT && interrupt_func && (*interrupt_func)() != NO_ERROR) + { + return er_errid (); + } + if (nbytes < 0) + { + return do_handle_network_error (nbytes); + } + + total_read += nbytes; + } + + // Step 5: Move the data into the block + cubmem::block blk (res_size, ext_blk.release_ptr()); + b = std::move (blk); + + return NO_ERROR; // Successfully received the buffer + } + + void + connection::invalidate () + { + pl_disconnect_server (m_socket); + } + + // private + void + connection::do_reconnect () + { + if (m_socket != INVALID_SOCKET) + { + pl_disconnect_server (m_socket); + } + + m_socket = pl_connect_server (m_pool->get_db_name (), m_pool->get_db_port ()); + if (m_socket != INVALID_SOCKET) + { + m_epoch = m_pool->get_epoch (); + } + } + + int + connection::do_handle_network_error (int nbytes) + { + (void) invalidate (); + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, nbytes); + return er_errid (); + } + +} // namespace cubpl diff --git a/src/sp/pl_connection.hpp b/src/sp/pl_connection.hpp new file mode 100644 index 00000000000..43358a8805c --- /dev/null +++ b/src/sp/pl_connection.hpp @@ -0,0 +1,176 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * pl_connection.hpp + */ + +#ifndef _PL_CONNECTION_POOL_HPP_ +#define _PL_CONNECTION_POOL_HPP_ + +#if !defined (SERVER_MODE) && !defined (SA_MODE) && !defined (PL_MODE) +#error Belongs to server module +#endif /* !defined (SERVER_MODE) && !defined (SA_MODE) */ + +#include +#include +#include +#include + +#include "porting.h" // SOCKET + +#include "error_code.h" +#include "mem_block.hpp" +#include "packer.hpp" +#include "pl_file.h" /* pl_read_info() */ +#include "network_callback_sr.hpp" + +namespace cubthread +{ + class entry; +} + +using pl_callback_func = std::function ; +using pl_callback_func_with_sock = std::function ; + +namespace cubpl +{ + ////////////////////////////////////////////////////////////////////////// + // Declarations + ////////////////////////////////////////////////////////////////////////// + // forward declaration + class connection; + + using connection_view = std::unique_ptr>; + + /********************************************************************* + * connection_pool - declaration + *********************************************************************/ + class EXPORT_IMPORT connection_pool + { + public: + connection_pool () = delete; + explicit connection_pool (int pool_size, const std::string &db_name, int pl_port = PL_PORT_DISABLED, + bool is_for_sys = false); + ~connection_pool (); + + connection_pool (connection_pool &&other) = delete; // Not MoveConstructible + connection_pool (const connection_pool ©) = delete; // Not CopyConstructible + + connection_pool &operator= (connection_pool &&other) = delete; // Not MoveAssignable + connection_pool &operator= (const connection_pool ©) = delete; // Not CopyAssignable + + connection_view claim (); + void retire (connection *claimed); + + void increment_epoch (); + + int get_pool_size () const; + int get_epoch () const; + + const char *get_db_name () const; + int get_db_port () const; + + bool is_system_pool () const; + + private: + explicit connection_pool (int pool_size); + void create_new_connection (int index); + connection_view get_connection_view (int index); + + + void initialize_pool (); + void cleanup_pool (); + + std::vector m_pool; + std::atomic m_epoch; // Whenever PL server is restarted, server_manager increments this value + + int m_min_conn_size; // minimum connection size + int m_inc_conn_size; // increment connection size for lazy initialization + + // for connection + std::string m_db_name; + int m_db_port; + + // blocking queue + std::queue m_queue; + std::mutex m_mutex; + }; + + /********************************************************************* + * connection - declaration + *********************************************************************/ + class EXPORT_IMPORT connection + { + friend connection_pool; + + public: + connection () = delete; + ~connection (); + + connection (const connection ©) = delete; // Not CopyConstructible + connection &operator= (const connection ©) = delete; // Not CopyAssignable + + connection (connection &&c) = delete; + connection &operator= (connection &&other) = delete; + + bool is_connected () const; + bool is_valid () const; + int get_index () const; + + int send_buffer (const cubmem::block &mem); + + int receive_buffer (cubmem::block &b); // simplified version + int receive_buffer (cubmem::block &b, const pl_callback_func *interrupt_func, int timeout_ms); + + template + int send_buffer_args (Args &&... args) + { + cubmem::block b = pack_data_block (std::forward (args)...); + int status = send_buffer (b); + if (b.is_valid ()) + { + delete [] b.ptr; + b.ptr = NULL; + b.dim = 0; + } + return status; + } + + void invalidate (); + + private: + explicit connection (connection_pool *pool, int index); + + void do_reconnect (); + int do_handle_network_error (int nbytes); + + SOCKET get_socket () const; + + connection_pool *m_pool; + int m_index; + SOCKET m_socket; + int m_epoch; // see connection_pool::m_epoch + }; +}; // namespace cubpl + +using PL_CONNECTION_POOL = cubpl::connection_pool; +using PL_CONNECTION_VIEW = cubpl::connection_view; +using PL_CONNECTION = cubpl::connection; + +#endif // _PL_CONNECTION_POOL_HPP_ diff --git a/src/sp/pl_execution_stack_context.cpp b/src/sp/pl_execution_stack_context.cpp new file mode 100644 index 00000000000..122faa0435d --- /dev/null +++ b/src/sp/pl_execution_stack_context.cpp @@ -0,0 +1,228 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "pl_execution_stack_context.hpp" + +#include "session.h" +#include "pl_sr.h" +#include "pl_comm.h" +#include "pl_connection.hpp" +#include "pl_query_cursor.hpp" + +#include "log_impl.h" + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" +namespace cubpl +{ + execution_stack::execution_stack (cubthread::entry *thread_p) + : m_id ((std::uint64_t) this) + , m_thread_p (thread_p) + , m_session {get_session ()} + , m_client_header (-1, METHOD_REQUEST_CALLBACK /* default */, 0) + , m_java_header (-1, SP_CODE_INTERNAL_JDBC /* default */, 0) + , m_connection {nullptr} + , m_req_id {0} + { + m_tid = logtb_find_current_tranid (thread_p); + m_is_running = false; + + if (m_session) + { + m_client_header.id = m_session->get_id (); + } + } + + execution_stack::~execution_stack () + { + if (m_session) + { + // retire connection + if (m_connection) + { + m_connection.reset (); + } + } + + destory_all_cursors (); + + m_session->pop_and_destroy_stack (get_id ()); + } + + void + execution_stack::add_query_handler (int handler_id) + { + m_stack_handler_id.insert (handler_id); + } + + void + execution_stack::remove_query_handler (int handler_id) + { + m_stack_handler_id.erase (handler_id); + } + + int + execution_stack::add_cursor (QUERY_ID query_id, bool oid_included) + { + if (query_id == NULL_QUERY_ID || query_id >= SHRT_MAX) + { + // false query e.g) SELECT * FROM db_class WHERE 0 <> 0 + return ER_FAILED; + } + + m_stack_cursor_id.insert (query_id); + + query_cursor *cursor = m_session->create_cursor (m_thread_p, query_id, oid_included); + return cursor ? NO_ERROR : ER_FAILED; + } + + query_cursor * + execution_stack::get_cursor (QUERY_ID query_id) + { + query_cursor *cursor = nullptr; + + if (query_id == NULL_QUERY_ID || query_id >= SHRT_MAX) + { + // false query e.g) SELECT * FROM db_class WHERE 0 <> 0 + return cursor; + } + + cursor = m_session->get_cursor (m_thread_p, query_id); + + /* + if (cursor == nullptr) + { + if (m_session->is_session_cursor (query_id)) + { + cursor = m_session->create_cursor (m_thread_p, query_id, false); + if (cursor) + { + // add to the clearing list at the end of stack + m_stack_cursor_id.insert (query_id); + } + } + } + */ + + return cursor; + } + + void + execution_stack::promote_to_session_cursor (QUERY_ID query_id) + { + m_session->add_session_cursor (m_thread_p, query_id); + + query_cursor *cursor = m_session->get_cursor (m_thread_p, query_id); + if (cursor) + { + cursor->change_owner (nullptr); + } + + m_stack_cursor_id.erase (query_id); + } + + void + execution_stack::destory_all_cursors () + { + for (auto &cursor_it : m_stack_cursor_id) + { + // If the cursor is received from the child function and is not returned to the parent function, the cursor remains in m_cursor_set. + // So here trying to find the cursor Id in the global returning cursor storage and remove it if exists. + m_session->remove_session_cursor (m_thread_p, cursor_it); + + m_session->destroy_cursor (m_thread_p, cursor_it); + } + + m_stack_cursor_id.clear (); + } + + connection_view & + execution_stack::get_connection () + { + if (m_connection == nullptr) + { + connection_pool *pool = get_connection_pool (); + if (pool) + { + m_connection = pool->claim (); + } + } + + return m_connection; + } + + PL_STACK_ID + execution_stack::get_id () const + { + return m_id; + } + + TRANID + execution_stack::get_tran_id () + { + m_tid = logtb_find_current_tranid (m_thread_p); + return m_tid; + } + + cubthread::entry * + execution_stack::get_thread_entry () const + { + return m_thread_p; + } + + + const std::unordered_set * + execution_stack::get_stack_query_handler () const + { + return &m_stack_handler_id; + } + + const std::unordered_set * + execution_stack::get_stack_cursor () const + { + return &m_stack_cursor_id; + } + + void + execution_stack::read_payload_block (cubpacking::unpacker &unpacker) + { + char *aligned_ptr = PTR_ALIGN (unpacker.get_curr_ptr(), MAX_ALIGNMENT); + size_t payload_size = (size_t) (unpacker.get_buffer_end() - aligned_ptr); + cubmem::block payload_blk (payload_size, aligned_ptr); + m_data_queue.emplace (std::move (payload_blk)); + } + + std::queue & + execution_stack::get_data_queue () + { + return m_data_queue; + } + + int + execution_stack::interrupt_handler () + { + bool dummy_continue; + if (logtb_is_interrupted (m_thread_p, true, &dummy_continue)) + { + m_session->set_local_error_for_interrupt (); + m_connection->invalidate (); + return m_session->get_interrupt_id (); + } + return NO_ERROR; + } +} diff --git a/src/sp/pl_execution_stack_context.hpp b/src/sp/pl_execution_stack_context.hpp new file mode 100644 index 00000000000..a9e5d2c9e01 --- /dev/null +++ b/src/sp/pl_execution_stack_context.hpp @@ -0,0 +1,188 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * pl_execution_stack_context.hpp: managing subprograms of a server task + */ + +#ifndef _PL_EXECUTION_STACK_HPP_ +#define _PL_EXECUTION_STACK_HPP_ + +#if !defined (SERVER_MODE) && !defined (SA_MODE) +#error Belongs to server module +#endif /* !defined (SERVER_MODE) && !defined (SA_MODE) */ + +#include + +#include "dbtype_def.h" +#include "error_manager.h" +#include "query_list.h" +#include "query_executor.h" +#include "mem_block.hpp" +#include "packer.hpp" + +#include "network_callback_sr.hpp" +#include "method_struct_invoke.hpp" +#include "pl_connection.hpp" + +// thread_entry.hpp +namespace cubthread +{ + class entry; +} + +using PL_STACK_ID = uint64_t; + +namespace cubpl +{ + class session; + class query_cursor; + + class execution_stack + { + protected: + PL_STACK_ID m_id; + TRANID m_tid; + + cubthread::entry *m_thread_p; + session *m_session; + + /* resources */ + std::unordered_set m_stack_handler_id; + std::unordered_set m_stack_cursor_id; + connection_view m_connection; + + /* error */ + std::string m_error_message; + + bool m_is_running; + + int interrupt_handler (); + + public: + execution_stack () = delete; // Not DefaultConstructible + execution_stack (cubthread::entry *thread_p); + + execution_stack (execution_stack &&other) = delete; // Not MoveConstructible + execution_stack (const execution_stack ©) = delete; // Not CopyConstructible + + execution_stack &operator= (execution_stack &&other) = delete; // Not MoveAssignable + execution_stack &operator= (const execution_stack ©) = delete; // Not CopyAssignable + + ~execution_stack (); + + /* getters */ + PL_STACK_ID get_id () const; + TRANID get_tran_id (); + + /* session and thread */ + cubthread::entry *get_thread_entry () const; + + /* connection */ + connection_view &get_connection (); + std::queue &get_data_queue (); + + /* resource management */ + int add_cursor (QUERY_ID query_id, bool oid_included); + void remove_cursor (QUERY_ID query_id); + query_cursor *get_cursor (QUERY_ID query_id); + void promote_to_session_cursor (QUERY_ID query_id); + void destory_all_cursors (); + + /* query handler */ + void add_query_handler (int handler_id); + void remove_query_handler (int handler_id); + + const std::unordered_set *get_stack_query_handler () const; + const std::unordered_set *get_stack_cursor () const; + + // runtime (temporary) + std::queue m_data_queue; + + cubmethod::header m_client_header; // header sending to cubridcs + cubmethod::header m_java_header; // header sending to cub_javasp + bool m_transaction_control; + + template + int send_data_to_client (const xs_callback_func &func, Args &&... args) + { + return xs_callback_send_and_receive (m_thread_p, func, m_client_header, std::forward (args)...); + } + + template + int send_data_to_java (Args &&... args) + { + m_java_header.req_id = get_and_increment_request_id (); + connection_view &conn = get_connection(); + if (!conn) + { + assert (er_errid () != NO_ERROR); + return er_errid (); // Handle the case where connection is unavailable + } + + return conn->send_buffer_args (m_java_header, std::forward (args)...); + } + + int + read_data_from_java (cubmem::block &b) + { + connection_view &conn = get_connection(); + if (!conn) + { + assert (er_errid () != NO_ERROR); + return er_errid (); // Handle the case where connection is unavailable + } + + pl_callback_func interrupt_func = [this]() + { + return interrupt_handler (); + }; + + return conn->receive_buffer (b, &interrupt_func, 500); + } + + void + set_command (int command) + { + m_java_header.command = command; + } + + int m_req_id; + inline int get_and_increment_request_id () + { + return m_req_id++; + } + + std::string m_error_msg; + void set_error_message (std::string error_msg) + { + m_error_message = error_msg; + } + + std::string get_error_message () + { + return m_error_message; + } + + void read_payload_block (cubpacking::unpacker &unpacker); + }; +} + +using PL_EXECUTION_STACK = cubpl::execution_stack; + +#endif //_PL_EXECUTION_STACK_HPP_ diff --git a/src/sp/pl_executor.cpp b/src/sp/pl_executor.cpp new file mode 100644 index 00000000000..86f113f6f67 --- /dev/null +++ b/src/sp/pl_executor.cpp @@ -0,0 +1,972 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "pl_executor.hpp" + +#include "regu_var.hpp" +#include "fetch.h" +#include "memory_alloc.h" + +// runtime +#include "dbtype.h" + +#include "method_struct_invoke.hpp" +#include "method_struct_query.hpp" +#include "method_struct_value.hpp" +#include "method_struct_oid_info.hpp" +#include "method_struct_parameter_info.hpp" + +#include "pl_comm.h" +#include "pl_query_cursor.hpp" +#include "sp_code.hpp" + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" +namespace cubpl +{ + using namespace cubmethod; + + invoke_java::invoke_java (uint64_t id, int tid, pl_signature *sig, bool tc) + : g_id (id) + , tran_id (tid) + { + signature.assign (sig->ext.sp.target_class_name).append (".").append (sig->ext.sp.target_method_name); + auth.assign (sig->auth); + lang = sig->type; + result_type = sig->result_type; + + pl_arg &arg = sig->arg; + num_args = arg.arg_size; + arg_mode.resize (num_args); + arg_type.resize (num_args); + + for (int i = 0; i < num_args; i++) + { + arg_mode[i] = arg.arg_mode[i]; + arg_type[i] = arg.arg_type[i]; + } + + transaction_control = (lang == SP_LANG_PLCSQL) ? true : tc; + } + + void + invoke_java::pack (cubpacking::packer &serializator) const + { + serializator.pack_bigint (g_id); + serializator.pack_int (tran_id); + serializator.pack_string (signature); + serializator.pack_string (auth); + serializator.pack_int (lang); + serializator.pack_int (num_args); + + for (int i = 0; i < num_args; i++) + { + serializator.pack_int (arg_mode[i]); + serializator.pack_int (arg_type[i]); + } + + serializator.pack_int (result_type); + serializator.pack_bool (transaction_control); + } + + void + invoke_java::unpack (cubpacking::unpacker &deserializator) + { + // TODO: unpacking is not necessary + assert (false); + } + + size_t + invoke_java::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const + { + size_t size = serializator.get_packed_bigint_size (start_offset); // group_id + size += serializator.get_packed_int_size (size); // tran_id + size += serializator.get_packed_string_size (signature, size); // signature + size += serializator.get_packed_string_size (auth, size); // auth + size += serializator.get_packed_int_size (size); // lang + size += serializator.get_packed_int_size (size); // num_args + + for (int i = 0; i < num_args; i++) + { + size += serializator.get_packed_int_size (size); // arg_mode + size += serializator.get_packed_int_size (size); // arg_type + } + + size += serializator.get_packed_int_size (size); // return_type + size += serializator.get_packed_bool_size (size); // transaction_control + return size; + } + + +////////////////////////////////////////////////// + executor::executor (pl_signature &sig) + : m_sig (sig) + { + m_stack = get_session ()->create_and_push_stack (nullptr); + } + + executor::~executor () + { + // destory local resources + pr_clear_value_vector (m_out_args); + + // exit stack + if (m_stack != nullptr) + { + delete m_stack; + } + } + + int + executor::fetch_args_peek (regu_variable_list_node *val_list_p, VAL_DESCR *val_desc_p, OID *obj_oid_p, + QFILE_TUPLE tuple) + { + int error = NO_ERROR; + int index = 0; + REGU_VARIABLE_LIST operand; + + if (m_stack == NULL) + { + return ER_FAILED; + } + + cubthread::entry *m_thread_p = m_stack->get_thread_entry (); + + if (m_sig.has_args ()) + { + DB_VALUE *value = NULL; + + operand = val_list_p; + while (operand != NULL) + { + error = fetch_peek_dbval (m_thread_p, &operand->value, val_desc_p, NULL, obj_oid_p, tuple, &value); + if (error != NO_ERROR) + { + m_args.clear (); + break; + } + + if (is_supported_dbtype (*value) == false) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_SUPPORTED_ARG_TYPE, 1, + pr_type_name ((DB_TYPE) value->domain.general_info.type)); + m_stack->set_error_message (std::string (er_msg ())); + error = er_errid (); + break; + } + + m_args.emplace_back (std::ref (*value)); + + operand = operand->next; + } + } + + return error; + } + + int + executor::fetch_args_peek (std::vector > args) + { + assert (m_args.empty ()); + m_args = args; + for (const DB_VALUE &val : m_args) + { + if (is_supported_dbtype (val) == false) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_SUPPORTED_ARG_TYPE, 1, + pr_type_name ((DB_TYPE) val.domain.general_info.type)); + m_stack->set_error_message (std::string (er_msg ())); + return er_errid (); + } + } + + return NO_ERROR; + } + + bool + executor::is_supported_dbtype (const DB_VALUE &value) + { + bool res = false; + switch (DB_VALUE_TYPE (&value)) + { + case DB_TYPE_INTEGER: + case DB_TYPE_SHORT: + case DB_TYPE_BIGINT: + case DB_TYPE_FLOAT: + case DB_TYPE_DOUBLE: + case DB_TYPE_MONETARY: + case DB_TYPE_NUMERIC: + case DB_TYPE_CHAR: + case DB_TYPE_NCHAR: + case DB_TYPE_VARNCHAR: + case DB_TYPE_STRING: + case DB_TYPE_DATE: + case DB_TYPE_TIME: + case DB_TYPE_TIMESTAMP: + case DB_TYPE_DATETIME: + case DB_TYPE_SET: + case DB_TYPE_MULTISET: + case DB_TYPE_SEQUENCE: + case DB_TYPE_OID: + case DB_TYPE_OBJECT: + case DB_TYPE_RESULTSET: + case DB_TYPE_NULL: + res = true; + break; + // unsupported types + case DB_TYPE_BIT: + case DB_TYPE_VARBIT: + case DB_TYPE_TABLE: + case DB_TYPE_BLOB: + case DB_TYPE_CLOB: + case DB_TYPE_TIMESTAMPTZ: + case DB_TYPE_TIMESTAMPLTZ: + case DB_TYPE_DATETIMETZ: + case DB_TYPE_DATETIMELTZ: + case DB_TYPE_JSON: + case DB_TYPE_ENUMERATION: + res = false; + break; + + // obsolete, internal, unused type + case DB_TYPE_ELO: + case DB_TYPE_VARIABLE: + case DB_TYPE_SUB: + case DB_TYPE_POINTER: + case DB_TYPE_ERROR: + case DB_TYPE_VOBJ: + case DB_TYPE_DB_VALUE: + case DB_TYPE_MIDXKEY: + default: + assert (false); + break; + } + return res; + } + + int + executor::execute (DB_VALUE &value) + { + int error = NO_ERROR; + + if (m_stack == NULL) + { + return ER_FAILED; + } + + // execution rights + assert (m_sig.auth != NULL); + error = change_exec_rights (m_sig.auth); + if (error != NO_ERROR) + { + goto exit; + } + + error = request_invoke_command (); + if (error != NO_ERROR) + { + goto exit; + } + + error = response_invoke_command (value); + if (error != NO_ERROR) + { + goto exit; + } + +exit: + // restore execution rights + change_exec_rights (NULL); + + return error; + } + + // runtime + int + executor::change_exec_rights (const char *auth_name) + { + int error = NO_ERROR; + int is_restore = (auth_name == NULL) ? 1 : 0; + + auto dummy = [&] (const cubmem::block & b) + { + return NO_ERROR; + }; + + if (is_restore == 0) + { + error = m_stack->send_data_to_client (dummy, METHOD_CALLBACK_CHANGE_RIGHTS, is_restore, std::string (auth_name)); + } + else + { + error = m_stack->send_data_to_client (dummy, METHOD_CALLBACK_CHANGE_RIGHTS, is_restore); + + } + + return error; + } + + int + executor::request_invoke_command () + { + int error = NO_ERROR; + + SESSION_ID sid = get_session ()->get_id (); + TRANID tid = m_stack->get_tran_id (); + + m_stack->set_command (SP_CODE_INVOKE); + prepare_args prepare_arg ((std::uint64_t) this, tid, METHOD_TYPE_PLCSQL, m_args); + invoke_java invoke_arg ((std::uint64_t) this, tid, &m_sig, prm_get_bool_value (PRM_ID_PL_TRANSACTION_CONTROL)); + + error = m_stack->send_data_to_java (prepare_arg, invoke_arg); + + return error; + } + + int + executor::response_invoke_command (DB_VALUE &value) + { + int error_code = NO_ERROR; + int start_code = -1; + + // response loop + do + { + cubmem::block response_blk; + error_code = m_stack->read_data_from_java (response_blk); + if (error_code != NO_ERROR) + { + break; + } + + cubpacking::unpacker unpacker (response_blk); + if (!response_blk.is_valid ()) + { + error_code = ER_SP_NETWORK_ERROR; + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 1, sizeof (int)); + break; + } + + unpacker.unpack_int (start_code); + + (void) m_stack->read_payload_block (unpacker); + + /* processing */ + if (start_code == SP_CODE_INTERNAL_JDBC) + { + error_code = response_callback_command (); + } + else if (start_code == SP_CODE_RESULT || start_code == SP_CODE_ERROR) + { + error_code = response_result (start_code, value); + } + else + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NETWORK_ERROR, 1, + start_code); + error_code = ER_SP_NETWORK_ERROR; + } + + if (m_stack->get_data_queue ().empty() == false) + { + m_stack->get_data_queue ().pop (); + } + + // free phase + if (response_blk.is_valid ()) + { + delete [] response_blk.ptr; + response_blk.ptr = NULL; + response_blk.dim = 0; + } + } + while (error_code == NO_ERROR && start_code == SP_CODE_INTERNAL_JDBC); + + return error_code; + } + + int + executor::response_result (int code, DB_VALUE &returnval) + { + // check queue + if (m_stack->get_data_queue().empty() == true) + { + return ER_FAILED; + } + + cubmem::block &blk = m_stack->get_data_queue().front (); + packing_unpacker unpacker (blk); + + if (code == SP_CODE_RESULT) + { + dbvalue_java value_unpacker; + db_make_null (&returnval); + value_unpacker.value = &returnval; + value_unpacker.unpack (unpacker); + + if (db_value_type (&returnval) == DB_TYPE_RESULTSET) + { + std::uint64_t query_id = db_get_resultset (&returnval); + if (query_id != NULL_QUERY_ID) + { + // qfile_update_qlist_count (thread_p, m_list_id, -1); + m_stack->promote_to_session_cursor (query_id); + } + } + + for (int i = 0; i < m_sig.arg.arg_size; i++) + { + DB_VALUE out_val; + db_make_null (&out_val); + if (m_sig.arg.arg_mode[i] != SP_MODE_IN) + { + value_unpacker.value = &out_val; + value_unpacker.unpack (unpacker); + m_out_args.emplace_back (out_val); + } + } + return NO_ERROR; + } + else if (code == SP_CODE_ERROR) + { + std::string error_msg; + unpacker.unpack_string (error_msg); + m_stack->set_error_message (error_msg); + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_EXECUTE_ERROR, 1, error_msg.c_str ()); + return ER_SP_EXECUTE_ERROR; + } + else + { + // it is handled in response_invoke_command + assert (false); + return ER_FAILED; + } + + return NO_ERROR; + } + + int + executor::response_callback_command () + { + int error_code = NO_ERROR; + // check queue + if (m_stack->get_data_queue().empty() == true) + { + return ER_FAILED; + } + + cubmem::block &blk = m_stack->get_data_queue().front (); + packing_unpacker unpacker (blk); + cubthread::entry &thread_ref = *m_stack->get_thread_entry (); + + int code; + unpacker.unpack_int (code); + + switch (code) + { + /* NOTE: we don't need to implement it + case METHOD_CALLBACK_GET_DB_VERSION: + break; + */ + + case METHOD_CALLBACK_GET_DB_PARAMETER: + error_code = callback_get_db_parameter (thread_ref, unpacker); + break; + + case METHOD_CALLBACK_QUERY_PREPARE: + error_code = callback_prepare (thread_ref, unpacker); + break; + + case METHOD_CALLBACK_QUERY_EXECUTE: + error_code = callback_execute (thread_ref, unpacker); + break; + + case METHOD_CALLBACK_FETCH: + error_code = callback_fetch (thread_ref, unpacker); + break; + + case METHOD_CALLBACK_OID_GET: + error_code = callback_oid_get (thread_ref, unpacker); + break; + + case METHOD_CALLBACK_OID_PUT: + error_code = callback_oid_put (thread_ref, unpacker); + break; + + case METHOD_CALLBACK_OID_CMD: + error_code = callback_oid_cmd (thread_ref, unpacker); + break; + + case METHOD_CALLBACK_COLLECTION: + error_code = callback_collection_cmd (thread_ref, unpacker); + break; + + case METHOD_CALLBACK_MAKE_OUT_RS: + error_code = callback_make_outresult (thread_ref, unpacker); + break; + + case METHOD_CALLBACK_GET_GENERATED_KEYS: + error_code = callback_get_generated_keys (thread_ref, unpacker); + break; + case METHOD_CALLBACK_END_TRANSACTION: + error_code = callback_end_transaction (thread_ref, unpacker); + break; + case METHOD_CALLBACK_CHANGE_RIGHTS: + error_code = callback_change_auth_rights (thread_ref, unpacker); + break; + case METHOD_CALLBACK_GET_CODE_ATTR: + error_code = callback_get_code_attr (thread_ref, unpacker); + break; + default: + // TODO: not implemented yet, do we need error handling? + assert (false); + error_code = ER_FAILED; + break; + } + + return error_code; + } + + std::vector & + executor::get_out_args () + { + return m_out_args; + } + + execution_stack * + executor::get_stack () + { + return m_stack; + } + + int + executor::callback_get_db_parameter (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_GET_DB_PARAMETER; + + db_parameter_info *parameter_info = get_session()->get_db_parameter_info (); + if (parameter_info == nullptr) + { + int tran_index = LOG_FIND_THREAD_TRAN_INDEX (m_stack->get_thread_entry()); + parameter_info = new db_parameter_info (); + + parameter_info->tran_isolation = logtb_find_isolation (tran_index); + parameter_info->wait_msec = logtb_find_wait_msecs (tran_index); + logtb_get_client_ids (tran_index, ¶meter_info->client_ids); + + get_session()->set_db_parameter_info (parameter_info); + } + + cubmem::block blk; + if (parameter_info) + { + blk = std::move (pack_data_block (METHOD_RESPONSE_SUCCESS, *parameter_info)); + } + else + { + blk = std::move (pack_data_block (METHOD_RESPONSE_ERROR, ER_FAILED, "unknown error", + ARG_FILE_LINE)); + } + + if (blk.is_valid ()) + { + m_stack->send_data_to_java (blk); + delete[] blk.ptr; + } + + return error; + } + + int + executor::callback_prepare (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_QUERY_PREPARE; + std::string sql; + int flag; + + unpacker.unpack_all (sql, flag); + + auto get_prepare_info = [&] (const cubmem::block & b) + { + packing_unpacker unpacker (b.ptr, (size_t) b.dim); + + int res_code; + unpacker.unpack_int (res_code); + + if (res_code == METHOD_RESPONSE_SUCCESS) + { + prepare_info info; + info.unpack (unpacker); + + m_stack->add_query_handler (info.handle_id); + } + + m_stack->send_data_to_java (b); + + return error; + }; + + error = m_stack->send_data_to_client (get_prepare_info, code, sql, flag, m_stack->get_tran_id ()); + return error; + } + + int + executor::callback_execute (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_QUERY_EXECUTE; + execute_request request; + + unpacker.unpack_all (request); + request.has_parameter = 1; + + auto get_execute_info = [&] (const cubmem::block & b) + { + packing_unpacker unpacker (b.ptr, (size_t) b.dim); + + int res_code; + unpacker.unpack_int (res_code); + + if (res_code == METHOD_RESPONSE_SUCCESS) + { + execute_info info; + info.unpack (unpacker); + + query_result_info ¤t_result_info = info.qresult_info; + int stmt_type = current_result_info.stmt_type; + if (stmt_type == CUBRID_STMT_SELECT) + { + std::uint64_t qid = current_result_info.query_id; + bool is_oid_included = current_result_info.include_oid; + (void) m_stack->add_cursor (qid, is_oid_included); + } + } + + error = m_stack->send_data_to_java (b); + return error; + }; + + error = m_stack->send_data_to_client (get_execute_info, code, request); + request.clear (); + + return error; + } + + int + executor::callback_fetch (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_FETCH; + std::uint64_t qid; + int pos; + int fetch_count; + int fetch_flag; + + unpacker.unpack_all (qid, pos, fetch_count, fetch_flag); + + /* find query cursor */ + query_cursor *cursor = m_stack->get_cursor (qid); + if (cursor == nullptr) + { + assert (false); + cubmem::block b = std::move (pack_data_block (METHOD_RESPONSE_ERROR, ER_FAILED, "unknown error", + ARG_FILE_LINE)); + error = m_stack->send_data_to_java (b); + return error; + } + + if (cursor->get_is_opened () == false) + { + cursor->open (); + } + + cursor->set_fetch_count (fetch_count); + + fetch_info info; + + SCAN_CODE s_code = S_SUCCESS; + + /* Most cases, fetch_count will be the same value + * To handle an invalid value of fetch_count is set at `cursor->set_fetch_count (fetch_count);` + * Here, I'm going to get the fetch_count from the getter again. + */ + fetch_count = cursor->get_fetch_count (); + + int start_index = cursor->get_current_index (); + while (s_code == S_SUCCESS) + { + s_code = cursor->next_row (); + int tuple_index = cursor->get_current_index (); + if (s_code == S_END || tuple_index - start_index >= fetch_count) + { + break; + } + + std::vector tuple_values = cursor->get_current_tuple (); + + if (cursor->get_is_oid_included()) + { + /* FIXME!!: For more optimized way, refactoring method_query_cursor is needed */ + OID *oid = cursor->get_current_oid (); + std::vector sub_vector = {tuple_values.begin() + 1, tuple_values.end ()}; + info.tuples.emplace_back (tuple_index, sub_vector, *oid); + } + else + { + info.tuples.emplace_back (tuple_index, tuple_values); + } + } + + cubmem::block blk; + if (s_code != S_ERROR) + { + blk = std::move (pack_data_block (METHOD_RESPONSE_SUCCESS, info)); + } + else + { + blk = std::move (pack_data_block (METHOD_RESPONSE_ERROR, ER_FAILED, "unknown error", + ARG_FILE_LINE)); + } + + error = m_stack->send_data_to_java (blk); + if (blk.is_valid ()) + { + delete [] blk.ptr; + blk.ptr = NULL; + blk.dim = 0; + } + + return error; + } + + int + executor::callback_oid_get (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_OID_GET; + oid_get_request request; + request.unpack (unpacker); + + auto java_lambda = [&] (const cubmem::block & b) + { + return m_stack->send_data_to_java (b); + }; + + error = m_stack->send_data_to_client (java_lambda, code, request); + return error; + } + + int + executor::callback_oid_put (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_OID_PUT; + oid_put_request request; + request.is_compatible_java = true; + request.unpack (unpacker); + request.is_compatible_java = false; + + auto java_lambda = [&] (const cubmem::block & b) + { + return m_stack->send_data_to_java (b); + }; + + error = m_stack->send_data_to_client (java_lambda, code, request); + return error; + } + + int + executor::callback_oid_cmd (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_OID_CMD; + int command; + OID oid; + unpacker.unpack_all (command, oid); + + auto java_lambda = [&] (const cubmem::block & b) + { + return m_stack->send_data_to_java (b); + }; + + error = m_stack->send_data_to_client (java_lambda, code, command, oid); + return error; + } + + int + executor::callback_collection_cmd (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + + int code = METHOD_CALLBACK_COLLECTION; + collection_cmd_request request; + request.is_compatible_java = true; + request.unpack (unpacker); + + request.is_compatible_java = false; + + auto java_lambda = [&] (const cubmem::block & b) + { + return m_stack->send_data_to_java (b); + }; + + error = m_stack->send_data_to_client (java_lambda, code, request); + return error; + } + + int + executor::callback_make_outresult (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + + int code = METHOD_CALLBACK_MAKE_OUT_RS; + uint64_t query_id; + unpacker.unpack_all (query_id); + + auto get_make_outresult_info = [&] (const cubmem::block & b) + { + packing_unpacker unpacker (b.ptr, (size_t) b.dim); + + int res_code; + make_outresult_info info; + unpacker.unpack_all (res_code, info); + + const query_result_info ¤t_result_info = info.qresult_info; + query_cursor *cursor = m_stack->get_cursor (current_result_info.query_id); + if (cursor) + { + cursor->change_owner (&thread_ref); + return m_stack->send_data_to_java (b); + } + else + { + assert (false); + return ER_FAILED; + } + }; + + error = m_stack->send_data_to_client (get_make_outresult_info, code, query_id); + + return error; + } + + int + executor::callback_get_generated_keys (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_GET_GENERATED_KEYS; + int handler_id; + unpacker.unpack_all (handler_id); + + auto java_lambda = [&] (const cubmem::block & b) + { + return m_stack->send_data_to_java (b); + }; + + error = m_stack->send_data_to_client (java_lambda, code, handler_id); + return error; + } + + int + executor::callback_end_transaction (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_END_TRANSACTION; + int command; // commit or abort + + unpacker.unpack_all (command); + + auto java_lambda = [&] (const cubmem::block & b) + { + return m_stack->send_data_to_java (b); + }; + + error = m_stack->send_data_to_client (java_lambda, code, command); + return error; + } + + int + executor::callback_change_auth_rights (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_CHANGE_RIGHTS; + + int command; + std::string auth_name; + + unpacker.unpack_all (command, auth_name); + + auto java_lambda = [&] (const cubmem::block & b) + { + return m_stack->send_data_to_java (b); + }; + + error = m_stack->send_data_to_client (java_lambda, code, command, auth_name); + return error; + } + + int + executor::callback_get_code_attr (cubthread::entry &thread_ref, packing_unpacker &unpacker) + { + int error = NO_ERROR; + int code = METHOD_CALLBACK_GET_CODE_ATTR; + + std::string attr_name; + + DB_VALUE res; + db_make_null (&res); + unpacker.unpack_all (attr_name); + + OID *code_oid = &m_sig.ext.sp.code_oid; + if (OID_ISNULL (code_oid)) + { + error = ER_FAILED; + } + + if (error == NO_ERROR) + { + error = sp_get_code_attr (&thread_ref, attr_name, code_oid, &res); + } + + cubmem::block blk; + if (error == NO_ERROR) + { + dbvalue_java java_packer; + java_packer.value = &res; + + blk = std::move (pack_data_block (error, java_packer)); + } + else + { + blk = std::move (pack_data_block (error)); + } + + db_value_clear (&res); + + error = m_stack->send_data_to_java (blk); + + if (blk.is_valid ()) + { + delete[] blk.ptr; + } + + return error; + } +} diff --git a/src/sp/pl_executor.hpp b/src/sp/pl_executor.hpp new file mode 100644 index 00000000000..8a848149970 --- /dev/null +++ b/src/sp/pl_executor.hpp @@ -0,0 +1,124 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * pl_executor.hpp + */ + +#ifndef _PL_EXECUTOR_HPP_ +#define _PL_EXECUTOR_HPP_ + +#if !defined (SERVER_MODE) && !defined (SA_MODE) +#error Belongs to server module +#endif /* !defined (SERVER_MODE) && !defined (SA_MODE) */ + +#include "pl_execution_stack_context.hpp" +#include "pl_signature.hpp" +#include "pl_session.hpp" + +// forward definitions +struct regu_variable_list_node; + +namespace cubpl +{ + struct invoke_java : public cubpacking::packable_object + { + invoke_java () = delete; + invoke_java (uint64_t g_id, int tran_id, pl_signature *sig, bool tc); + + void pack (cubpacking::packer &serializator) const override; + void unpack (cubpacking::unpacker &deserializator) override; + size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; + + uint64_t g_id; + int tran_id; + + std::string signature; + std::string auth; + int lang; + int num_args; + std::vector arg_mode; + std::vector arg_type; + int result_type; + + bool transaction_control; // TODO: wrap it with proper structs + }; + + class executor + { + public: + executor () = delete; // Not DefaultConstructible + executor (pl_signature &sig); + + executor (executor &&other) = delete; // Not MoveConstructible + executor (const executor ©) = delete; // Not CopyConstructible + + executor &operator= (executor &&other) = delete; // Not MoveAssignable + executor &operator= (const executor ©) = delete; // Not CopyAssignable + + ~executor (); + + // args + int fetch_args_peek (regu_variable_list_node *val_list_p, VAL_DESCR *val_desc_p, OID *obj_oid_p, + QFILE_TUPLE tuple); // QUERY + int fetch_args_peek (std::vector > args); // CALL + + // execute + int execute (DB_VALUE &value); + + // getter + std::vector &get_out_args (); + execution_stack *get_stack (); + + private: + execution_stack *m_stack; + pl_signature &m_sig; + + std::vector > m_args; + std::vector m_out_args; + + // check + int check_unsupported_dbtype (); + bool is_supported_dbtype (const DB_VALUE &val); + + int change_exec_rights (const char *auth_name); + + // command handling + int request_invoke_command (); + int response_invoke_command (DB_VALUE &value); + + int response_result (int code, DB_VALUE &returnval); + int response_callback_command (); + + int callback_get_db_parameter (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_prepare (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_execute (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_fetch (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_oid_get (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_oid_put (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_oid_cmd (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_collection_cmd (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_make_outresult (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_get_generated_keys (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_end_transaction (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_change_auth_rights (cubthread::entry &thread_ref, packing_unpacker &unpacker); + int callback_get_code_attr (cubthread::entry &thread_ref, packing_unpacker &unpacker); + }; +} + +#endif \ No newline at end of file diff --git a/src/sp/jsp_file.c b/src/sp/pl_file.c similarity index 54% rename from src/sp/jsp_file.c rename to src/sp/pl_file.c index 5723cd01bdc..f5ded88f9f7 100644 --- a/src/sp/jsp_file.c +++ b/src/sp/pl_file.c @@ -18,7 +18,7 @@ /* - * jsp_file.c - Functions to manage files related to Java Stored Procedure Server + * pl_file.c - Functions to manage files related to Java Stored Procedure Server * * Note: */ @@ -27,7 +27,7 @@ #include #endif -#include "jsp_file.h" +#include "pl_file.h" #include "porting.h" #include "environment_variable.h" @@ -40,28 +40,28 @@ #include "memory_wrapper.hpp" bool -javasp_open_info_dir () +pl_open_info_dir () { - char javasp_dir[PATH_MAX]; - envvar_vardir_file (javasp_dir, sizeof (javasp_dir), "javasp"); + char pl_dir[PATH_MAX]; + envvar_vardir_file (pl_dir, sizeof (pl_dir), "pl"); - if (access (javasp_dir, F_OK) < 0) + if (access (pl_dir, F_OK) < 0) { /* create directory if not exist */ - if (mkdir (javasp_dir, 0777) < 0 && errno == ENOENT) + if (mkdir (pl_dir, 0777) < 0 && errno == ENOENT) { char pdir[PATH_MAX]; - if (cub_dirname_r (javasp_dir, pdir, PATH_MAX) > 0 && access (pdir, F_OK) < 0) + if (cub_dirname_r (pl_dir, pdir, PATH_MAX) > 0 && access (pdir, F_OK) < 0) { mkdir (pdir, 0777); } } } - if (access (javasp_dir, F_OK) < 0) + if (access (pl_dir, F_OK) < 0) { - if (mkdir (javasp_dir, 0777) < 0) + if (mkdir (pl_dir, 0777) < 0) { return false; } @@ -71,13 +71,13 @@ javasp_open_info_dir () } FILE * -javasp_open_info (const char *db_name, const char *mode) +pl_open_info (const char *db_name, const char *mode) { FILE *fp = NULL; char file_name[PATH_MAX] = { 0 }; char file_path[PATH_MAX] = { 0 }; - snprintf (file_name, PATH_MAX, "javasp/javasp_%s.info", db_name); + snprintf (file_name, PATH_MAX, "pl/pl_%s.info", db_name); envvar_vardir_file (file_path, PATH_MAX, file_name); fp = fopen (file_path, mode); @@ -86,24 +86,24 @@ javasp_open_info (const char *db_name, const char *mode) } void -javasp_unlink_info (const char *db_name) +pl_unlink_info (const char *db_name) { char file_name[PATH_MAX] = { 0 }; char file_path[PATH_MAX] = { 0 }; - snprintf (file_name, PATH_MAX, "javasp/javasp_%s.info", db_name); + snprintf (file_name, PATH_MAX, "pl/pl_%s.info", db_name); envvar_vardir_file (file_path, PATH_MAX, file_name); unlink (file_path); } bool -javasp_get_info_file (char *buf, size_t len, const char *db_name) +pl_get_info_file (char *buf, size_t len, const char *db_name) { - char javasp_vardir[PATH_MAX]; - envvar_vardir_file (javasp_vardir, PATH_MAX, "javasp"); + char pl_vardir[PATH_MAX]; + envvar_vardir_file (pl_vardir, PATH_MAX, "pl"); - if (snprintf (buf, len, "%s/javasp_%s.info", javasp_vardir, db_name) < 0) + if (snprintf (buf, len, "%s/pl_%s.info", pl_vardir, db_name) < 0) { assert (false); buf[0] = '\0'; @@ -113,12 +113,12 @@ javasp_get_info_file (char *buf, size_t len, const char *db_name) } bool -javasp_get_error_file (char *buf, size_t len, const char *db_name) +pl_get_error_file (char *buf, size_t len, const char *db_name) { - char javasp_logdir[PATH_MAX]; - envvar_logdir_file (javasp_logdir, sizeof (javasp_logdir), ""); + char pl_logdir[PATH_MAX]; + envvar_logdir_file (pl_logdir, sizeof (pl_logdir), ""); - if (snprintf (buf, len, "%s/%s_java.err", javasp_logdir, db_name) < 0) + if (snprintf (buf, len, "%s/%s_java.err", pl_logdir, db_name) < 0) { assert (false); buf[0] = '\0'; @@ -128,12 +128,12 @@ javasp_get_error_file (char *buf, size_t len, const char *db_name) } bool -javasp_get_log_file (char *buf, size_t len, const char *db_name) +pl_get_log_file (char *buf, size_t len, const char *db_name) { - char javasp_logdir[PATH_MAX]; - envvar_logdir_file (javasp_logdir, sizeof (javasp_logdir), ""); + char pl_logdir[PATH_MAX]; + envvar_logdir_file (pl_logdir, sizeof (pl_logdir), ""); - if (snprintf (buf, len, "%s/%s_java.log", javasp_logdir, db_name) < 0) + if (snprintf (buf, len, "%s/%s_java.log", pl_logdir, db_name) < 0) { assert (false); buf[0] = '\0'; @@ -143,11 +143,11 @@ javasp_get_log_file (char *buf, size_t len, const char *db_name) } bool -javasp_read_info (const char *db_name, JAVASP_SERVER_INFO & info) +pl_read_info (const char *db_name, PL_SERVER_INFO & info) { FILE *fp = NULL; - fp = javasp_open_info (db_name, "r"); + fp = pl_open_info (db_name, "r"); if (fp) { fscanf (fp, "%d %d", &info.pid, &info.port); @@ -159,12 +159,12 @@ javasp_read_info (const char *db_name, JAVASP_SERVER_INFO & info) } bool -javasp_write_info (const char *db_name, JAVASP_SERVER_INFO info) +pl_write_info (const char *db_name, PL_SERVER_INFO info) { bool result = false; FILE *fp = NULL; - fp = javasp_open_info (db_name, "w+"); + fp = pl_open_info (db_name, "w+"); if (fp) { fprintf (fp, "%d %d", info.pid, info.port); @@ -175,8 +175,8 @@ javasp_write_info (const char *db_name, JAVASP_SERVER_INFO info) } bool -javasp_reset_info (const char *db_name) +pl_reset_info (const char *db_name) { - JAVASP_SERVER_INFO reset_info = JAVASP_SERVER_INFO_INITIALIZER; - return javasp_write_info (db_name, reset_info); + PL_SERVER_INFO reset_info = PL_SERVER_INFO_INITIALIZER; + return pl_write_info (db_name, reset_info); } diff --git a/src/sp/pl_file.h b/src/sp/pl_file.h new file mode 100644 index 00000000000..5817e326f1f --- /dev/null +++ b/src/sp/pl_file.h @@ -0,0 +1,69 @@ +/* + * Copyright 2008 Search Solution Corporation + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +/* + * pl_file.h - Functions to manage files related to Java Stored Procedure Server + * + * Note: + */ + +#ifndef _PL_FILE_H_ +#define _PL_FILE_H_ + +#ident "$Id$" + +#include "porting.h" +#include + +typedef struct pl_server_info PL_SERVER_INFO; +struct pl_server_info +{ + int pid; + int port; +}; + +#define PL_PID_DISABLED -1 +#define PL_PORT_DISABLED -2 +#define PL_PORT_UDS_MODE -1 + +#define PL_SERVER_INFO_INITIALIZER \ + {PL_PID_DISABLED, PL_PORT_DISABLED} + +#ifdef __cplusplus +extern "C" +{ +#endif + + extern EXPORT_IMPORT bool pl_open_info_dir (); + extern EXPORT_IMPORT FILE *pl_open_info (const char *db_name, const char *mode); + extern EXPORT_IMPORT void pl_unlink_info (const char *db_name); + + extern EXPORT_IMPORT bool pl_read_info (const char *db_name, PL_SERVER_INFO & info); + extern EXPORT_IMPORT bool pl_write_info (const char *db_name, PL_SERVER_INFO info); + extern EXPORT_IMPORT bool pl_reset_info (const char *db_name); + + extern EXPORT_IMPORT bool pl_get_info_file (char *buf, size_t len, const char *db_name); + extern EXPORT_IMPORT bool pl_get_error_file (char *buf, size_t len, const char *db_name); + extern EXPORT_IMPORT bool pl_get_log_file (char *buf, size_t len, const char *db_name); + +#ifdef __cplusplus +} +#endif + +#endif /* _PL_FILE_H_ */ diff --git a/src/method/method_query_cursor.cpp b/src/sp/pl_query_cursor.cpp similarity index 89% rename from src/method/method_query_cursor.cpp rename to src/sp/pl_query_cursor.cpp index 5d88a20d89d..fe45842899a 100644 --- a/src/method/method_query_cursor.cpp +++ b/src/sp/pl_query_cursor.cpp @@ -16,27 +16,34 @@ * */ -#include "method_query_cursor.hpp" +#include "pl_query_cursor.hpp" #include "dbtype.h" #include "dbtype_def.h" #include "list_file.h" #include "log_impl.h" #include "object_representation.h" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" -namespace cubmethod +namespace cubpl { query_cursor::query_cursor (cubthread::entry *thread_p, QMGR_QUERY_ENTRY *query_entry_p, bool oid_included) : m_thread (thread_p) , m_is_oid_included (oid_included) , m_is_opened (false) , m_fetch_count (1000) // FIXME: change the fixed value, 1000 + , m_query_id (0) { reset (query_entry_p); } + query_cursor::~query_cursor () + { + close (); + } + int query_cursor::reset (QMGR_QUERY_ENTRY *query_entry_p) { @@ -127,6 +134,10 @@ namespace cubmethod } } } + else if (scan_code == S_END) + { + close (); + } return scan_code; } @@ -174,6 +185,10 @@ namespace cubmethod } } } + else if (scan_code == S_END) + { + close (); + } return scan_code; } @@ -181,7 +196,15 @@ namespace cubmethod void query_cursor::change_owner (cubthread::entry *thread_p) { - if (m_thread->get_id () == thread_p->get_id ()) + if (thread_p == nullptr) + { + close (); + // qfile_update_qlist_count (m_thread, m_list_id, -1); + m_thread = nullptr; + return; + } + + if (m_thread != nullptr && m_thread->get_id () == thread_p->get_id ()) { return; } @@ -192,7 +215,13 @@ namespace cubmethod m_thread = thread_p; // m_list_id is going to be destoryed on server-side, so that qlist_count has to be updated - qfile_update_qlist_count (thread_p, m_list_id, 1); + // qfile_update_qlist_count (thread_p, m_list_id, 1); + } + + cubthread::entry * + query_cursor::get_owner () const + { + return m_thread; } std::vector @@ -201,8 +230,6 @@ namespace cubmethod return m_current_tuple; } - void clear (); - int query_cursor::get_current_index () { @@ -257,4 +284,5 @@ namespace cubmethod m_fetch_count = cnt; } } + } diff --git a/src/method/method_query_cursor.hpp b/src/sp/pl_query_cursor.hpp similarity index 87% rename from src/method/method_query_cursor.hpp rename to src/sp/pl_query_cursor.hpp index dd63d62e909..b2351a2ff8d 100644 --- a/src/method/method_query_cursor.hpp +++ b/src/sp/pl_query_cursor.hpp @@ -17,11 +17,11 @@ */ // -// method_query_cursor.hpp +// pl_query_cursor.hpp // -#ifndef _METHOD_QUERY_CURSOR_HPP_ -#define _METHOD_QUERY_CURSOR_HPP_ +#ifndef _PL_QUERY_CURSOR_HPP_ +#define _PL_QUERY_CURSOR_HPP_ #ident "$Id$" @@ -29,7 +29,7 @@ #include "dbtype_def.h" #include "query_list.h" /* QUERY_ID, QFILE_LIST_ID */ -#include "query_manager.h" +#include "query_manager.h" /* QMGR_QUERY_ENTRY */ // thread_entry.hpp namespace cubthread @@ -37,12 +37,13 @@ namespace cubthread class entry; } -namespace cubmethod +namespace cubpl { class query_cursor { public: query_cursor (cubthread::entry *thread_p, QMGR_QUERY_ENTRY *query_entry_p, bool is_oid_included = false); + ~query_cursor (); int open (); void close (); @@ -68,10 +69,11 @@ namespace cubmethod int get_tuple_value (int index, DB_VALUE &result); bool get_is_oid_included (); bool get_is_opened (); - int get_fetch_count (); void set_fetch_count (int cnt); + cubthread::entry *get_owner () const; + private: cubthread::entry *m_thread; /* which thread owns this cursor */ @@ -90,4 +92,6 @@ namespace cubmethod }; } // namespace cubmethod -#endif /* _METHOD_QUERY_CURSOR_HPP_ */ +using PL_QUERY_CURSOR = cubpl::query_cursor; + +#endif /* _PL_QUERY_CURSOR_HPP_ */ diff --git a/src/method/method_runtime_context.cpp b/src/sp/pl_session.cpp similarity index 55% rename from src/method/method_runtime_context.cpp rename to src/sp/pl_session.cpp index 1bac8533267..331c81a4324 100644 --- a/src/method/method_runtime_context.cpp +++ b/src/sp/pl_session.cpp @@ -16,139 +16,171 @@ * */ -#include "method_runtime_context.hpp" +#include "pl_session.hpp" -#include "method_query_cursor.hpp" +#include "pl_query_cursor.hpp" #include "query_manager.h" #include "session.h" #include "xserver_interface.h" #include "thread_manager.hpp" #include "method_error.hpp" + +#include "method_struct_parameter_info.hpp" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" -namespace cubmethod +namespace cubpl { ////////////////////////////////////////////////////////////////////////// // Global interface ////////////////////////////////////////////////////////////////////////// - runtime_context *get_rctx (cubthread::entry *thread_p) + session *get_session () { - method_runtime_context *rctx = nullptr; - session_get_method_runtime_context (thread_p, rctx); - return rctx; + session *s = nullptr; + cubthread::entry *thread_p = thread_get_thread_entry_info (); + session_get_pl_session (thread_p, s); + return s; } ////////////////////////////////////////////////////////////////////////// // Runtime Context ////////////////////////////////////////////////////////////////////////// - runtime_context::runtime_context () + session::session () : m_mutex () - , m_group_stack {} - , m_returning_cursors {} - , m_group_map {} + , m_exec_stack {} + , m_stack_idx {-1} + , m_session_cursors {} + , m_stack_map {} , m_cursor_map {} , m_is_interrupted (false) , m_interrupt_id (NO_ERROR) , m_is_running (false) - , m_conn_pool (METHOD_MAX_RECURSION_DEPTH + 1) , m_req_id {0} + , m_param_info {nullptr} { - // + m_exec_stack.reserve (METHOD_MAX_RECURSION_DEPTH + 1); } - runtime_context::~runtime_context () + session::~session () { - destroy_all_groups (); + } - method_invoke_group * - runtime_context::create_invoke_group (cubthread::entry *thread_p, const method_sig_list &sig_list, bool is_scan) + execution_stack * + session::create_and_push_stack (cubthread::entry *thread_p) { - std::unique_lock ulock (m_mutex); + if (thread_p == nullptr) + { + thread_p = thread_get_thread_entry_info (); + } - method_invoke_group *group = new cubmethod::method_invoke_group (thread_p, sig_list, is_scan); - if (group) + // check interrupt + if (is_interrupted () && m_stack_idx > -1) { - m_group_map [group->get_id ()] = group; + // block creating a new stack + set_local_error_for_interrupt (); + m_cond_var.notify_all (); + return nullptr; } - return group; - } - void - runtime_context::push_stack (cubthread::entry *thread_p, method_invoke_group *group) - { std::unique_lock ulock (m_mutex); - m_is_running = true; - m_group_stack.push_back (group->get_id ()); + execution_stack *stack = new execution_stack (thread_p); + if (stack) + { + m_stack_map [stack->get_id ()] = stack; + + // update stack index + m_stack_idx++; + + // push to exec_stack + int stack_size = (int) m_exec_stack.size (); + PL_STACK_ID stack_id = stack->get_id (); + if (m_stack_idx < stack_size) + { + m_exec_stack [m_stack_idx] = stack_id; + } + else + { + m_exec_stack.emplace_back (stack_id); + } + + m_is_running = true; + } + else + { + set_interrupt (ER_OUT_OF_VIRTUAL_MEMORY); + } + + return stack; } void - runtime_context::pop_stack (cubthread::entry *thread_p, method_invoke_group *claimed) + session::pop_and_destroy_stack (const PL_STACK_ID sid) { - std::unique_lock ulock (m_mutex); - - if (claimed->is_for_scan () && m_group_stack.back() != claimed->get_id ()) + if (m_stack_idx == -1) { - // push deferred - // When beginning method_invoke_group with method scan, method_invoke_group belonging to child node in XASL is pushed first (postorder) - // When method_invoke_group is ended while clearing XASL by qexec_clear_xasl(), method_invoke_group belonging to the parent node in XASL is poped first (preorder) - // Because of these differences, I've introduced the m_deferred_free_stack structure to follow the order of clearing according to the XASL structure when clearing method_invoke_groups from the m_group_stack. - m_deferred_free_stack.push_back (claimed->get_id ()); + // interrupted return; } auto pred = [&] () -> bool { // condition to check - return m_group_stack.back() == claimed->get_id (); + return m_exec_stack[m_stack_idx] == sid; }; // Guaranteed to be removed from the topmost element + std::unique_lock ulock (m_mutex); m_cond_var.wait (ulock, pred); if (pred ()) { - destroy_group (m_group_stack.back ()); - m_group_stack.pop_back (); - } + if (m_stack_idx > -1) + { + m_exec_stack[m_stack_idx] = -1; + m_stack_idx--; + } - // should be freed for all XASL structure - while (m_deferred_free_stack.empty () == false && m_deferred_free_stack.back () == m_group_stack.back()) - { - destroy_group (m_group_stack.back ()); - m_group_stack.pop_back (); - m_deferred_free_stack.pop_back (); + m_stack_map.erase (sid); } - if (m_group_stack.empty()) + if (m_stack_idx < 0) { - // reset interrupt state - m_is_interrupted = false; - m_interrupt_id = NO_ERROR; m_is_running = false; - // notify m_group_stack becomes empty (); - ulock.unlock (); - m_cond_var.notify_all (); + // clear interrupt + m_is_interrupted = false; + m_interrupt_id = NO_ERROR; + m_interrupt_msg.clear (); } + + ulock.unlock (); + m_cond_var.notify_all (); } - method_invoke_group * - runtime_context::top_stack () + execution_stack * + session::top_stack () { std::unique_lock ulock (m_mutex); - if (m_group_stack.empty()) + + return top_stack_internal (); + } + + execution_stack * + session::top_stack_internal () + { + if (m_exec_stack.empty()) { return nullptr; } - METHOD_GROUP_ID top = m_group_stack.back (); - const auto &it = m_group_map.find (top); - if (it == m_group_map.end ()) + PL_STACK_ID top = m_exec_stack[m_stack_idx]; + const auto &it = m_stack_map.find (top); + if (it == m_stack_map.end ()) { // should not happended assert (false); @@ -158,8 +190,25 @@ namespace cubmethod return it->second; } + bool + session::is_thread_involved (thread_id_t id) + { + std::unique_lock ulock (m_mutex); + + for (const auto &it : m_stack_map) + { + execution_stack *stack = it.second; + if (stack->get_thread_entry () && id == stack->get_thread_entry ()->get_id ()) + { + return true; + } + } + + return false; + } + void - runtime_context::set_interrupt (int reason, std::string msg) + session::set_interrupt (int reason, std::string msg) { switch (reason) { @@ -189,36 +238,36 @@ namespace cubmethod } void - runtime_context::set_local_error_for_interrupt () + session::set_local_error_for_interrupt () { - handle_method_error (get_interrupt_id (), get_interrupt_msg ()); + cubmethod::handle_method_error (get_interrupt_id (), get_interrupt_msg ()); } bool - runtime_context::is_interrupted () + session::is_interrupted () { return m_is_interrupted; } int - runtime_context::get_interrupt_id () + session::get_interrupt_id () { return m_interrupt_id; } std::string - runtime_context::get_interrupt_msg () + session::get_interrupt_msg () { return m_interrupt_msg; } void - runtime_context::wait_for_interrupt () + session::wait_for_interrupt () { auto pred = [this] () -> bool { // condition of finish - return m_group_stack.empty () && is_running () == false; + return is_running () == false; }; if (pred ()) @@ -226,24 +275,32 @@ namespace cubmethod return; } + m_cond_var.notify_all (); + std::unique_lock ulock (m_mutex); m_cond_var.wait (ulock, pred); } int - runtime_context::get_depth () + session::get_depth () + { + return m_stack_map.size () - m_deferred_free_stack.size (); + } + + SESSION_ID + session::get_id () { - return m_group_map.size () - m_deferred_free_stack.size (); + return m_id; } bool - runtime_context::is_running () + session::is_running () { return m_is_running; } query_cursor * - runtime_context::get_cursor (cubthread::entry *thread_p, QUERY_ID query_id) + session::get_cursor (cubthread::entry *thread_p, QUERY_ID query_id) { if (query_id == NULL_QUERY_ID) { @@ -264,7 +321,7 @@ namespace cubmethod } query_cursor * - runtime_context::create_cursor (cubthread::entry *thread_p, QUERY_ID query_id, bool is_oid_included) + session::create_cursor (cubthread::entry *thread_p, QUERY_ID query_id, bool is_oid_included) { if (query_id == NULL_QUERY_ID || query_id >= SHRT_MAX) { @@ -308,7 +365,7 @@ namespace cubmethod } void - runtime_context::destroy_cursor (cubthread::entry *thread_p, QUERY_ID query_id) + session::destroy_cursor (cubthread::entry *thread_p, QUERY_ID query_id) { if (query_id == NULL_QUERY_ID) { @@ -316,7 +373,11 @@ namespace cubmethod return; } - std::unique_lock ulock (m_mutex); + // TODo + // std::unique_lock ulock (m_mutex); + + // remove from session cursor map + // m_session_cursors.erase (query_id); // safe guard // find in map auto search = m_cursor_map.find (query_id); @@ -338,7 +399,7 @@ namespace cubmethod } void - runtime_context::register_returning_cursor (cubthread::entry *thread_p, QUERY_ID query_id) + session::add_session_cursor (cubthread::entry *thread_p, QUERY_ID query_id) { if (query_id == NULL_QUERY_ID) { @@ -346,14 +407,13 @@ namespace cubmethod return; } - std::unique_lock ulock (m_mutex); + // std::unique_lock ulock (m_mutex); - m_returning_cursors.insert (query_id); - // m_cursor_map.erase (query_id); + m_session_cursors.insert (query_id); } void - runtime_context::deregister_returning_cursor (cubthread::entry *thread_p, QUERY_ID query_id) + session::remove_session_cursor (cubthread::entry *thread_p, QUERY_ID query_id) { if (query_id == NULL_QUERY_ID) { @@ -361,69 +421,51 @@ namespace cubmethod return; } - std::unique_lock ulock (m_mutex); + // std::unique_lock ulock (m_mutex); - m_returning_cursors.erase (query_id); + m_session_cursors.erase (query_id); } - void - runtime_context::destroy_group (METHOD_GROUP_ID id) + bool + session::is_session_cursor (QUERY_ID query_id) { - // assume that lock is already acquired - // std::unique_lock ulock (m_mutex); - - // find in map - auto search = m_group_map.find (id); - if (search != m_group_map.end ()) + if (m_session_cursors.find (query_id) != m_session_cursors.end ()) { - method_invoke_group *group = search->second; - if (group) - { - delete group; - } - m_group_map.erase (search); + return true; } - } - - void - runtime_context::destroy_all_groups () - { - std::unique_lock ulock (m_mutex); - for (auto &it : m_group_map) + else { - if (it.second) - { - delete it.second; - } + return false; } - m_group_map.clear (); } void - runtime_context::destroy_all_cursors () + session::destroy_all_cursors () { std::unique_lock ulock (m_mutex); for (auto &it : m_cursor_map) { - /* - if (cubthread::get_manager () != NULL) - { - destroy_cursor (&cubthread::get_entry (), it.first); - } - */ - if (it.second) + query_cursor *cursor = it.second; + if (cursor) { + destroy_cursor (cursor->get_owner (), it.first /* QUERY_ID */); delete it.second; } } m_cursor_map.clear (); - m_returning_cursors.clear (); + m_session_cursors.clear (); } - connection_pool & - runtime_context::get_connection_pool () + cubmethod::db_parameter_info * + session::get_db_parameter_info () const + { + return m_param_info; + } + + void + session::set_db_parameter_info (cubmethod::db_parameter_info *param_info) { - return m_conn_pool; + m_param_info = param_info; } } // cubmethod diff --git a/src/method/method_runtime_context.hpp b/src/sp/pl_session.hpp similarity index 62% rename from src/method/method_runtime_context.hpp rename to src/sp/pl_session.hpp index c4aae4427af..b8282958bf4 100644 --- a/src/method/method_runtime_context.hpp +++ b/src/sp/pl_session.hpp @@ -17,11 +17,11 @@ */ // -// method_runtime_context.hpp +// pl_session.hpp // -#ifndef _METHOD_RUNTIME_CONTEXT_HPP_ -#define _METHOD_RUNTIME_CONTEXT_HPP_ +#ifndef _PL_SESSION_HPP_ +#define _PL_SESSION_HPP_ #if !defined (SERVER_MODE) && !defined (SA_MODE) #error Belongs to server module @@ -34,8 +34,10 @@ #include #include -#include "method_connection_pool.hpp" -#include "method_def.hpp" +#include "pl_connection.hpp" + +#include "pl_execution_stack_context.hpp" +#include "pl_signature.hpp" // thread_entry.hpp namespace cubthread @@ -45,41 +47,53 @@ namespace cubthread namespace cubmethod { - // forward declarations class method_invoke_group; + class db_parameter_info; +} + +namespace cubpl +{ + // forward declarations class query_cursor; - class connection_pool; + class execution_stack; using THREAD_ENTRY_IDX = int; using QUERY_ID = std::uint64_t; - class runtime_context + class session { public: - runtime_context (); - ~runtime_context (); + session (); + ~session (); - using invoke_group_map_type = std::unordered_map ; - using invoke_group_stack_type = std::deque ; - using invoke_group_iter = std::unordered_map ::iterator; + using exec_stack_map_type = std::unordered_map ; + using exec_stack_id_type = std::vector ; + using exec_stack_iter = std::unordered_map ::iterator; using cursor_map_type = std::unordered_map ; using cursor_iter = std::unordered_map ::iterator; + /* cursor management */ query_cursor *create_cursor (cubthread::entry *thread_p, QUERY_ID query_id, bool oid_included = false); query_cursor *get_cursor (cubthread::entry *thread_p, QUERY_ID query_id); void destroy_cursor (cubthread::entry *thread_p, QUERY_ID query_id); - void register_returning_cursor (cubthread::entry *thread_p, QUERY_ID query_id); - void deregister_returning_cursor (cubthread::entry *thread_p, QUERY_ID query_id); - - method_invoke_group *create_invoke_group (cubthread::entry *thread_p, const method_sig_list &siglist, bool is_scan); + void add_session_cursor (cubthread::entry *thread_p, QUERY_ID query_id); + void remove_session_cursor (cubthread::entry *thread_p, QUERY_ID query_id); + bool is_session_cursor (QUERY_ID query_id); + /* stack management */ // Currently these functions are used for debugging purpose. // In the recursive call situation, each time the function is called, a new worker from the thread pool is assigned. With this code, you can easily know the current state. // In the future, these functions will resolve some cases when it is necessary to set an error for all threads participating in a recursive call e.g. interrupt - void push_stack (cubthread::entry *thread_p, method_invoke_group *group); - void pop_stack (cubthread::entry *thread_p, method_invoke_group *claimed); - method_invoke_group *top_stack (); + execution_stack *create_and_push_stack (cubthread::entry *thread_p); + void pop_and_destroy_stack (const PL_STACK_ID sid); + execution_stack *top_stack (); + + /* thread */ + bool is_thread_involved (thread_id_t id); + + /* getter */ + SESSION_ID get_id (); void set_interrupt (int reason, std::string msg = ""); bool is_interrupted (); @@ -98,41 +112,45 @@ namespace cubmethod return m_req_id++; } - connection_pool &get_connection_pool (); + cubmethod::db_parameter_info *get_db_parameter_info () const; + void set_db_parameter_info (cubmethod::db_parameter_info *param_info); private: - void destroy_group (METHOD_GROUP_ID id); - - void destroy_all_groups (); + execution_stack *top_stack_internal (); void destroy_all_cursors (); std::mutex m_mutex; std::condition_variable m_cond_var; - invoke_group_stack_type m_group_stack; // runtime stack - std::unordered_set m_returning_cursors; + std::unordered_set m_session_cursors; - invoke_group_map_type m_group_map; // method executor storage - cursor_map_type m_cursor_map; // server-side cursor storage + exec_stack_map_type m_stack_map; // method executor storage + exec_stack_id_type m_exec_stack; // runtime stack (implemented using vector) + int m_stack_idx; - invoke_group_stack_type m_deferred_free_stack; - connection_pool m_conn_pool; + cursor_map_type m_cursor_map; // server-side cursor storage + + exec_stack_id_type m_deferred_free_stack; std::atomic m_req_id; + cubmethod::db_parameter_info *m_param_info; + bool m_is_interrupted; int m_interrupt_id; std::string m_interrupt_msg; bool m_is_running; + + SESSION_ID m_id; }; /* global interface */ - runtime_context *get_rctx (cubthread::entry *thread_p); + session *get_session (); } // cubmethod // alias declaration for legacy C files -using method_runtime_context = cubmethod::runtime_context; +using PL_SESSION = cubpl::session; -#endif // _METHOD_RUNTIME_CONTEXT_HPP_ \ No newline at end of file +#endif // _PL_SESSION_HPP_ diff --git a/src/sp/pl_signature.cpp b/src/sp/pl_signature.cpp new file mode 100644 index 00000000000..2978426ec22 --- /dev/null +++ b/src/sp/pl_signature.cpp @@ -0,0 +1,429 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "pl_signature.hpp" + +#include +#include "memory_alloc.h" +#include "memory_private_allocator.hpp" +#include "sp_constants.hpp" + +#if defined (SERVER_MODE) +#include "thread_manager.hpp" +#endif + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" + +#define CHECK_NULL_AND_FREE(owner, val) \ + do { \ + if (val != nullptr) \ + { \ + db_private_free_and_init (owner, val); \ + } \ + } while(0) + +namespace cubpl +{ + static const char *EMPTY_STRING = ""; + + pl_arg::pl_arg () + : pl_arg (0) + {} + + pl_arg::pl_arg (int num_args) + : arg_size {num_args} + { +#if defined (SERVER_MODE) + owner = thread_get_thread_entry_info (); +#else + owner = NULL; +#endif + set_arg_size (num_args); + } + + pl_arg::~pl_arg () + { + clear (); + } + + void + pl_arg::clear () + { + if (arg_size > 0) + { + CHECK_NULL_AND_FREE (owner, arg_mode); + CHECK_NULL_AND_FREE (owner, arg_type); + for (int i = 0; i < arg_size; i++) + { + if (arg_default_value_size && arg_default_value_size[i] > 0) + { + CHECK_NULL_AND_FREE (owner, arg_default_value[i]); + } + } + CHECK_NULL_AND_FREE (owner, arg_default_value_size); + CHECK_NULL_AND_FREE (owner, arg_default_value); + } + } + + void + pl_arg::pack (cubpacking::packer &serializator) const + { + serializator.pack_int (arg_size); + + if (arg_size > 0) + { + serializator.pack_int_array (arg_mode, arg_size); + serializator.pack_int_array (arg_type, arg_size); + } + } + + void + pl_arg::unpack (cubpacking::unpacker &deserializator) + { + deserializator.unpack_int (arg_size); + + if (arg_size > 0) + { + set_arg_size (arg_size); + + int cnt; + deserializator.unpack_int_array (arg_mode, cnt); + assert (arg_size == cnt); + + deserializator.unpack_int_array (arg_type, cnt); + assert (arg_size == cnt); + } + } + + size_t + pl_arg::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const + { + size_t size = serializator.get_packed_int_size (start_offset); // arg_size + if (arg_size > 0) + { + size += serializator.get_packed_int_vector_size (size, arg_size); // arg_mode + size += serializator.get_packed_int_vector_size (size, arg_size); // arg_type + } + return size; + } + + void + pl_arg::set_arg_size (int num_args) + { + clear (); + if (num_args > 0) + { + arg_size = num_args; + arg_mode = (int *) db_private_alloc (NULL, (num_args) * sizeof (int)); + arg_type = (int *) db_private_alloc (NULL, (num_args) * sizeof (int)); + arg_default_value_size = (int *) db_private_alloc (NULL, (num_args) * sizeof (int)); + arg_default_value = (char **) db_private_alloc (NULL, (num_args) * sizeof (char *)); + for (int i = 0; i < num_args; i++) + { + arg_mode[i] = 0; + arg_type[i] = 0; + arg_default_value_size[i] = 0; + arg_default_value[i] = nullptr; + } + } + else + { + arg_size = 0; + arg_mode = nullptr; + arg_type = nullptr; + arg_default_value_size = nullptr; + arg_default_value = nullptr; + } + } + + pl_signature::pl_signature () + : name {nullptr} + , auth {nullptr} + , type {0} + , result_type {0} + { +#if defined (SERVER_MODE) + owner = thread_get_thread_entry_info (); +#else + owner = NULL; +#endif + memset (&ext, 0, sizeof (pl_ext)); + } + + pl_signature::~pl_signature () + { + CHECK_NULL_AND_FREE (owner, name); + CHECK_NULL_AND_FREE (owner, auth); + + if (PL_TYPE_IS_METHOD (type)) + { + CHECK_NULL_AND_FREE (owner, ext.method.class_name); + CHECK_NULL_AND_FREE (owner, ext.method.arg_pos); + } + else + { + CHECK_NULL_AND_FREE (owner, ext.sp.target_class_name); + CHECK_NULL_AND_FREE (owner, ext.sp.target_method_name); + } + } + + void + pl_signature::pack (cubpacking::packer &serializator) const + { + serializator.pack_int (type); + serializator.pack_c_string (name, strlen (name)); + + serializator.pack_bool (auth != nullptr); + if (auth) + { + serializator.pack_c_string (auth, strlen (auth)); + } + + serializator.pack_int (result_type); + + // arg + arg.pack (serializator); + + // ext + if (PL_TYPE_IS_METHOD (type)) + { + serializator.pack_bool (ext.method.class_name != nullptr); + if (ext.method.class_name) + { + serializator.pack_c_string (ext.method.class_name, strlen (ext.method.class_name)); + } + if (arg.arg_size > 0) + { + serializator.pack_int_array (ext.method.arg_pos, arg.arg_size); + } + } + else + { + serializator.pack_bool (ext.sp.target_class_name != nullptr); + if (ext.sp.target_class_name) + { + serializator.pack_c_string (ext.sp.target_class_name, strlen (ext.sp.target_class_name)); + } + serializator.pack_bool (ext.sp.target_method_name != nullptr); + if (ext.sp.target_method_name) + { + serializator.pack_c_string (ext.sp.target_method_name, strlen (ext.sp.target_method_name)); + } + serializator.pack_oid (ext.sp.code_oid); + } + } + + void + pl_signature::unpack (cubpacking::unpacker &deserializator) + { + deserializator.unpack_int (type); + + cubmem::extensible_block name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR }; + deserializator.unpack_string_to_memblock (name_blk); + name = name_blk.release_ptr (); + + bool has_auth = false; + deserializator.unpack_bool (has_auth); + if (has_auth) + { + cubmem::extensible_block auth_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR }; + deserializator.unpack_string_to_memblock (auth_name_blk); + auth = auth_name_blk.release_ptr (); + } + else + { + auth = nullptr; + } + + deserializator.unpack_int (result_type); + + arg.unpack (deserializator); + + // ext + if (PL_TYPE_IS_METHOD (type)) + { + bool has_cn = false; + deserializator.unpack_bool (has_cn); + if (has_cn) + { + cubmem::extensible_block class_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR }; + deserializator.unpack_string_to_memblock (class_name_blk); + ext.method.class_name = class_name_blk.release_ptr (); + } + else + { + ext.method.class_name = nullptr; + } + + if (arg.arg_size > 0) + { + ext.method.arg_pos = (int *) db_private_alloc (NULL, sizeof (int) * arg.arg_size); + int cnt; + deserializator.unpack_int_array (ext.method.arg_pos, cnt); + assert (cnt == arg.arg_size); + } + else + { + ext.method.arg_pos = nullptr; + } + } + else + { + bool has_n = false; + deserializator.unpack_bool (has_n); + if (has_n) + { + cubmem::extensible_block class_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR }; + deserializator.unpack_string_to_memblock (class_name_blk); + ext.sp.target_class_name = class_name_blk.release_ptr (); + } + else + { + ext.sp.target_class_name = nullptr; + } + + deserializator.unpack_bool (has_n); + if (has_n) + { + cubmem::extensible_block class_name_blk { cubmem::PRIVATE_BLOCK_ALLOCATOR }; + deserializator.unpack_string_to_memblock (class_name_blk); + ext.sp.target_method_name = class_name_blk.release_ptr (); + } + else + { + ext.sp.target_method_name = nullptr; + } + + deserializator.unpack_oid (ext.sp.code_oid); + } + } + + size_t + pl_signature::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const + { + size_t size = serializator.get_packed_int_size (start_offset); /* type */ + + size += serializator.get_packed_c_string_size (name, strlen (name), size); // name + size += serializator.get_packed_bool_size (size); // has auth + if (auth) + { + size += serializator.get_packed_c_string_size (auth, strlen (auth), size); + } + + size += serializator.get_packed_int_size (size); /* result_type */ + + size += arg.get_packed_size (serializator, size); // arg + + if (PL_TYPE_IS_METHOD (type)) + { + size += serializator.get_packed_bool_size (size); // has class_name + if (ext.method.class_name) + { + size += serializator.get_packed_c_string_size (ext.method.class_name, strlen (ext.method.class_name), size); + } + + if (arg.arg_size > 0) + { + size += serializator.get_packed_int_vector_size (size, arg.arg_size); // arg_pos + } + } + else + { + size += serializator.get_packed_bool_size (size); // has target_class_name + if (ext.sp.target_class_name) + { + size += serializator.get_packed_c_string_size (ext.sp.target_class_name, strlen (ext.sp.target_class_name), size); + } + size += serializator.get_packed_bool_size (size); // has target_method_name + if (ext.sp.target_method_name) + { + size += serializator.get_packed_c_string_size (ext.sp.target_method_name, strlen (ext.sp.target_method_name), size); + } + + size += serializator.get_packed_oid_size (size); // code_oid + } + + return size; + } + + bool + pl_signature::has_args () + { + return arg.arg_size > 0; + } + + pl_signature_array::pl_signature_array () + :pl_signature_array (0) + {} + + pl_signature_array::pl_signature_array (int num) + : num_sigs {num} + { +#if defined (SERVER_MODE) + owner = thread_get_thread_entry_info (); +#else + owner = NULL; +#endif + sigs = (num > 0) ? new pl_signature[num] : nullptr; + } + + pl_signature_array::~pl_signature_array () + { + if (sigs) + { + delete [] sigs; + sigs = nullptr; + } + } + + void + pl_signature_array::pack (cubpacking::packer &serializator) const + { + serializator.pack_int (num_sigs); + for (int i = 0; i < num_sigs; i++) + { + sigs[i].pack (serializator); + } + } + + void + pl_signature_array::unpack (cubpacking::unpacker &deserializator) + { + deserializator.unpack_int (num_sigs); + if (num_sigs > 0) + { + sigs = new pl_signature [num_sigs]; + for (int i = 0; i < num_sigs; i++) + { + sigs[i].unpack (deserializator); + } + } + } + + size_t + pl_signature_array::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const + { + size_t size = serializator.get_packed_int_size (start_offset); /* num_sigs */ + for (int i = 0; i < num_sigs; i++) + { + size += sigs[i].get_packed_size (serializator, size); + } + return size; + } +} diff --git a/src/sp/pl_signature.hpp b/src/sp/pl_signature.hpp new file mode 100644 index 00000000000..9cb8e7a6b34 --- /dev/null +++ b/src/sp/pl_signature.hpp @@ -0,0 +1,131 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// +// pl_signature.hpp +// + +#ifndef _PL_SIGNATURE_HPP_ +#define _PL_SIGNATURE_HPP_ + +#include "packable_object.hpp" +#include "thread_compat.hpp" + +enum PL_TYPE +{ + PL_TYPE_NONE = 0, + PL_TYPE_INSTANCE_METHOD, + PL_TYPE_CLASS_METHOD, + PL_TYPE_JAVA_SP, + PL_TYPE_PLCSQL +}; + +enum PL_ARG_DEFAULT +{ + PL_ARG_DEFAULT_NONE = -1, + PL_ARG_DEFAULT_NULL = 0 +}; + +namespace cubpl +{ +#define PL_TYPE_IS_METHOD(type) \ + ((type) == PL_TYPE_INSTANCE_METHOD || (type) == PL_TYPE_CLASS_METHOD) + + struct pl_arg : public cubpacking::packable_object + { + THREAD_ENTRY *owner; + + int arg_size; + int *arg_mode; // array of (IN|OUT|IN/OUT) + int *arg_type; // array of DB_TYPE + + // Only used in runtime + int *arg_default_value_size; + char **arg_default_value; + + void pack (cubpacking::packer &serializator) const override; + void unpack (cubpacking::unpacker &deserializator) override; + size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; + + pl_arg (); + pl_arg (int num_args); + ~pl_arg () override; + + void set_arg_size (int num_args); + void clear (); + }; + + union pl_ext + { + struct pl_sp_info + { + char *target_class_name; + char *target_method_name; + OID code_oid; // PL/CSQL + } sp; + struct pl_method_info + { + char *class_name; + int *arg_pos; + } method; + }; + + struct pl_signature : public cubpacking::packable_object + { + THREAD_ENTRY *owner; + + int type; // PL_TYPE + char *name; + char *auth; + int result_type; // DB_TYPE + + pl_arg arg; + pl_ext ext; + + void pack (cubpacking::packer &serializator) const override; + void unpack (cubpacking::unpacker &deserializator) override; + size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; + + bool has_args (); + + pl_signature (); + ~pl_signature () override; + }; + + struct pl_signature_array : public cubpacking::packable_object + { + THREAD_ENTRY *owner; + + int num_sigs; + pl_signature *sigs; + + void pack (cubpacking::packer &serializator) const override; + void unpack (cubpacking::unpacker &deserializator) override; + size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; + + pl_signature_array (); + pl_signature_array (int num); + ~pl_signature_array () override; + }; +} + +using PL_SIGNATURE_TYPE = cubpl::pl_signature; +using PL_SIGNATURE_ARG_TYPE = cubpl::pl_arg; +using PL_SIGNATURE_ARRAY_TYPE = cubpl::pl_signature_array; + +#endif // _PL_SIGNATURE_HPP_ diff --git a/src/sp/jsp_sr.h b/src/sp/pl_signature_packing_helper.hpp similarity index 55% rename from src/sp/jsp_sr.h rename to src/sp/pl_signature_packing_helper.hpp index afab1c06afe..8c3abcf302f 100644 --- a/src/sp/jsp_sr.h +++ b/src/sp/pl_signature_packing_helper.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2008 Search Solution Corporation + * * Copyright 2016 CUBRID Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,30 +16,15 @@ * */ +// +// pl_signature_packing_helper.hpp +// -/* - * jsp_sr.h - Java Stored Procedure Server Module Header - * - * Note: - */ - -#ifndef _JSP_SR_H_ -#define _JSP_SR_H_ - -#ident "$Id$" +#ifndef _PL_SIGNATURE_PACKING_HELPER_HPP_ +#define _PL_SIGNATURE_PACKING_HELPER_HPP_ -#if defined(__cplusplus) -extern "C" -{ -#endif +#include "pl_signature.hpp" - extern int jsp_start_server (const char *server_name, const char *path, int port_number); - extern int jsp_server_port (void); - extern int jsp_server_port_from_info (void); - extern int jsp_jvm_is_loaded (void); -#if defined(__cplusplus) -} -#endif -#endif /* _JSP_SR_H_ */ +#endif \ No newline at end of file diff --git a/src/sp/pl_sr.cpp b/src/sp/pl_sr.cpp new file mode 100644 index 00000000000..b567cf5e7ef --- /dev/null +++ b/src/sp/pl_sr.cpp @@ -0,0 +1,621 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * pl_sr.cpp - PL Server Module Source + */ + +#include "pl_sr.h" + +#if defined (SERVER_MODE) || defined (SA_MODE) +#include "boot_sr.h" +#endif + +#if !defined(WINDOWS) +#include +#include +#endif + +#include "thread_manager.hpp" +#include "thread_task.hpp" +#if defined (SERVER_MODE) +#include "thread_entry.hpp" +#include "thread_looper.hpp" +#include "thread_daemon.hpp" +#else +#include "dbi.h" +#include "boot.h" +#endif + +#include "dbtype.h" +#include "pl_comm.h" +#include "pl_connection.hpp" +#include "process_util.h" +#include "environment_variable.h" +#include "system_parameter.h" +#include "release_string.h" +#include "memory_alloc.h" +#include "error_manager.h" +#include "method_struct_invoke.hpp" +#include "method_struct_value.hpp" + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" +namespace cubpl +{ +////////////////////////////////////////////////////////////////////////// +// Declarations +////////////////////////////////////////////////////////////////////////// + + class server_monitor_task; + + /********************************************************************* + * server_manager - declaration + *********************************************************************/ + class server_manager final + { + public: + static constexpr std::size_t CONNECTION_POOL_SIZE = 100; + + explicit server_manager (const char *db_name); + + ~server_manager (); + + server_manager (const server_manager ©) = delete; // Not CopyConstructible + server_manager &operator= (const server_manager ©) = delete; // Not CopyAssignable + + server_manager (server_manager &&other) = delete; // Not MoveConstructible + server_manager &operator= (server_manager &&other) = delete; // Not MoveAssignable + + /* + * start () - start the PL server through monitoring task + */ + void start (); + + /* + * wait_for_server_ready() - check if the server is ready to accept connection + */ + void wait_for_server_ready (); + + /* + * get_connection_pool() - get the connection pool + */ + connection_pool *get_connection_pool (); + + private: + + server_monitor_task *m_server_monitor_task; + connection_pool *m_connection_pool; + +#if defined (SERVER_MODE) + cubthread::daemon *m_monitor_helper_daemon = nullptr; +#endif + }; + + /********************************************************************* + * server_monitor_task - declaration + *********************************************************************/ + +#if defined (SERVER_MODE) + class server_monitor_task : public cubthread::entry_task +#else + class server_monitor_task +#endif + { + public: + enum server_monitor_state + { + SERVER_MONITOR_STATE_INIT, + SERVER_MONITOR_STATE_RUNNING, + SERVER_MONITOR_STATE_STOPPED, + SERVER_MONITOR_STATE_HANG, + SERVER_MONITOR_STATE_UNKNOWN + }; + + server_monitor_task (server_manager *manager, const char *db_name); + ~server_monitor_task (); + + server_monitor_task (const server_monitor_task ©) = delete; // Not CopyConstructible + server_monitor_task &operator= (const server_monitor_task ©) = delete; // Not CopyAssignable + + server_monitor_task (server_monitor_task &&other) = delete; // Not MoveConstructible + server_monitor_task &operator= (server_monitor_task &&other) = delete; // Not MoveAssignable + +#if defined (SERVER_MODE) + // called by daemon thread + void execute (context_type &thread_ref) override; +#endif + + // internal main routine + // This function is called by daemon thread (SERVER_MODE) or main thread (SA_MODE) + void do_monitor (); + + // wait until PL server is initialized + void wait_for_ready (); + + private: + void do_initialize (); + + // check functions for PL server state + void do_check_state (bool hang_check); + int do_check_connection (); + + /* + * do_bootstrap_request() - send a bootstrap request to PL server + */ + int do_bootstrap_request (); + + server_manager *m_manager; + + int m_pid; + server_monitor_state m_state; + std::string m_db_name; + std::string m_binary_name; + std::string m_executable_path; + const char *m_argv[3]; + + connection_pool *m_sys_conn_pool; + + std::mutex m_monitor_mutex; + std::condition_variable m_monitor_cv; + }; + + struct pl_ctx_params + { + int param_id; + DB_VALUE param_value; + }; + + struct bootstrap_request : public cubpacking::packable_object + { + std::vector static_params; + + bootstrap_request (SYSPRM_ASSIGN_VALUE *pl_ctx_values); + ~bootstrap_request (); + + void pack (cubpacking::packer &serializator) const override; + void unpack (cubpacking::unpacker &deserializator) override; + size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; + }; + +////////////////////////////////////////////////////////////////////////// +// Definitions +////////////////////////////////////////////////////////////////////////// + + /********************************************************************* + * server_manager - definition + *********************************************************************/ + server_manager::server_manager (const char *db_name) + { + m_server_monitor_task = new server_monitor_task (this, db_name); +#if defined (SERVER_MODE) + m_monitor_helper_daemon = nullptr; +#endif + m_connection_pool = new connection_pool (server_manager::CONNECTION_POOL_SIZE, db_name); + } + + server_manager::~server_manager () + { +#if defined (SERVER_MODE) + if (m_monitor_helper_daemon) + { + cubthread::get_manager ()->destroy_daemon (m_monitor_helper_daemon); + } + + if (m_connection_pool) + { + delete m_connection_pool; + m_connection_pool = nullptr; + } +#endif + } + + void + server_manager::start () + { +#if defined (SERVER_MODE) + cubthread::looper looper = cubthread::looper (std::chrono::milliseconds (1000)); + m_monitor_helper_daemon = cubthread::get_manager ()->create_daemon (looper, m_server_monitor_task, "pl_monitor"); +#else + m_server_monitor_task->do_monitor (); +#endif + } + + void + server_manager::wait_for_server_ready () + { + m_server_monitor_task->wait_for_ready (); + } + + connection_pool * + server_manager::get_connection_pool () + { + return m_connection_pool; + } + + /********************************************************************* + * server_monitor_task - definition + *********************************************************************/ + server_monitor_task::server_monitor_task (server_manager *manager, const char *db_name) + : m_manager (manager) + , m_pid (-1) + , m_state (SERVER_MONITOR_STATE_INIT) + , m_db_name (db_name) + , m_binary_name ("cub_pl") + , m_argv {m_binary_name.c_str (), m_db_name.c_str (), 0} + , m_sys_conn_pool {nullptr} + , m_monitor_mutex {} + , m_monitor_cv {} + { + char executable_path[PATH_MAX]; + (void) envvar_bindir_file (executable_path, PATH_MAX, m_binary_name.c_str ()); + m_executable_path.assign (executable_path, PATH_MAX); + } + + server_monitor_task::~server_monitor_task () + { + // do nothing + } + +#if defined (SERVER_MODE) + void + server_monitor_task::execute (context_type &thread_ref) + { + if (!BO_IS_SERVER_RESTARTED ()) + { + // wait for boot to finish + return; + } + + do_monitor (); + } +#endif + + void + server_monitor_task::do_monitor () + { + (void) do_check_state (false); + + if (m_state == SERVER_MONITOR_STATE_HANG) + { + terminate_process (m_pid); + } + + if (m_state != SERVER_MONITOR_STATE_RUNNING) + { + int status; + int pid = create_child_process (m_executable_path.c_str (), m_argv, 0 /* do not wait */, nullptr, nullptr, nullptr, + &status); + if (pid <= 0) + { + // do nothing + } + else // parent + { + m_pid = pid; + do_initialize (); + } + } + } + + void + server_monitor_task::wait_for_ready () + { + auto pred = [this] () -> bool { return m_state == SERVER_MONITOR_STATE_RUNNING; }; + + std::unique_lock ulock (m_monitor_mutex); + m_monitor_cv.wait (ulock, pred); + } + + void + server_monitor_task::do_initialize () + { + int error = ER_FAILED; + std::lock_guard lock (m_monitor_mutex); + // wait PL server is ready to accept connection (polling) + + constexpr int MAX_FAIL_COUNT = 10; + int fail_count = 0; + while (fail_count < MAX_FAIL_COUNT) + { + error = do_check_connection (); + if (error != NO_ERROR) + { + fail_count++; + (void) sleep (1); + } + else + { + break; + } + } + + if (error == NO_ERROR) + { + error = do_bootstrap_request (); + } + + if (error != NO_ERROR) + { + m_state = SERVER_MONITOR_STATE_UNKNOWN; + terminate_process (m_pid); + } + else + { + // re-initialize connection pool + m_manager->get_connection_pool ()->increment_epoch (); + + // notify server is ready + m_state = SERVER_MONITOR_STATE_RUNNING; + } + + m_monitor_cv.notify_all(); + } + + void + server_monitor_task::do_check_state (bool hang_check) + { + if (m_pid > 0) + { + if (!is_terminated_process (m_pid)) + { + // If process is running but ping command through UDS (TCP) does not respond, then it is considered as hang + if (hang_check && do_check_connection () != NO_ERROR) + { + m_state = SERVER_MONITOR_STATE_HANG; + } + else + { + m_state = SERVER_MONITOR_STATE_RUNNING; + } + } + else + { + m_state = SERVER_MONITOR_STATE_STOPPED; + } + } + } + + int + server_monitor_task::do_check_connection () + { + int error = NO_ERROR; + + if (m_sys_conn_pool == nullptr) + { + m_sys_conn_pool = new connection_pool (5, m_db_name, pl_server_port_from_info (), true); + } + + cubmem::block ping_response; + connection_view cv = m_sys_conn_pool->claim (); + cubmethod::header header (DB_EMPTY_SESSION, SP_CODE_UTIL_PING, 0); + + auto ping = [&] () + { + int error = cv->send_buffer_args (header); + if (error == NO_ERROR) + { + error = cv->receive_buffer (ping_response); + } + return error; + }; + + error = ping (); + if (error != NO_ERROR) + { + // retry + error = ping (); + } + +exit: + if (ping_response.is_valid ()) + { + delete [] ping_response.ptr; + ping_response.ptr = NULL; + ping_response.dim = 0; + } + + cv.reset (); + + return (error); + } + + int + server_monitor_task::do_bootstrap_request () + { + cubmem::block bootstrap_response; + cubmethod::header header (DB_EMPTY_SESSION, SP_CODE_UTIL_BOOTSTRAP, 0); + connection_view cv = m_sys_conn_pool->claim (); + + int error = NO_ERROR; + + SYSPRM_ASSIGN_VALUE *pl_ctx_params_assignments = xsysprm_get_pl_context_parameters (); + bootstrap_request bootstrap_request (pl_ctx_params_assignments); + error = cv->send_buffer_args (header, bootstrap_request); + if (error == NO_ERROR) + { + error = cv->receive_buffer (bootstrap_response); + } + + if (error == NO_ERROR && bootstrap_response.is_valid ()) + { + packing_unpacker deserializator (bootstrap_response); + deserializator.unpack_int (error); + } + + sysprm_free_assign_values (&pl_ctx_params_assignments); + + return error; + } + + /********************************************************************* + * bootstrap_request - definition + *********************************************************************/ + bootstrap_request::bootstrap_request (SYSPRM_ASSIGN_VALUE *pl_ctx_values) + : static_params () + { + int idx = 0; + while (pl_ctx_values != nullptr) + { + PARAM_ID param_id = pl_ctx_values->prm_id; + + pl_ctx_params param_obj; + param_obj.param_id = (int) param_id; + + if (PRM_IS_BOOLEAN (GET_PRM (param_id))) + { + int val = prm_get_bool_value (param_id) ? 1 : 0; + db_make_int (¶m_obj.param_value, val); + } + else if (PRM_IS_STRING (GET_PRM (param_id))) + { + const char *val = prm_get_string_value (param_id); + if (val == NULL) + { + switch (param_id) + { + case PRM_ID_INTL_COLLATION: + val = lang_get_collation_name (LANG_GET_BINARY_COLLATION (LANG_SYS_CODESET)); + break; + case PRM_ID_INTL_DATE_LANG: + case PRM_ID_INTL_NUMBER_LANG: + val = lang_get_Lang_name (); + break; + case PRM_ID_TIMEZONE: + val = prm_get_string_value (PRM_ID_SERVER_TIMEZONE); + break; + default: + /* do nothing */ + break; + } + } + db_make_string (¶m_obj.param_value, val); + } + else + { + // not implemented yet + assert (false); + } + static_params.push_back (param_obj); + + idx++; + pl_ctx_values = pl_ctx_values->next; + } + } + + bootstrap_request::~bootstrap_request () + { + for (pl_ctx_params ¶m : static_params) + { + db_value_clear (¶m.param_value); + } + } + + void + bootstrap_request::pack (cubpacking::packer &serializator) const + { + serializator.pack_int (static_params.size ()); + cubmethod::dbvalue_java sp_val; + for (const pl_ctx_params ¶m : static_params) + { + serializator.pack_int (param.param_id); + sp_val.value = (DB_VALUE *) ¶m.param_value; + sp_val.pack (serializator); + } + } + + void + bootstrap_request::unpack (cubpacking::unpacker &deserializator) + { + // do nothing + } + + size_t + bootstrap_request::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const + { + size_t size = serializator.get_packed_int_size (start_offset); // static_params.size () + + cubmethod::dbvalue_java sp_val; + for (const pl_ctx_params ¶m : static_params) + { + size += serializator.get_packed_int_size (size); // param.param_id + sp_val.value = (DB_VALUE *) ¶m.param_value; + size += sp_val.get_packed_size (serializator, size); + } + + return size; + } + +} // namespace cubpl + +////////////////////////////////////////////////////////////////////////// +// High Level API for PL server module +////////////////////////////////////////////////////////////////////////// + +static cubpl::server_manager *pl_server_manager = nullptr; + +void +pl_server_init (const char *db_name) +{ + if (pl_server_manager != nullptr || prm_get_bool_value (PRM_ID_STORED_PROCEDURE) == false) + { + return; + } + +#if defined (SA_MODE) + if (!BOOT_NORMAL_CLIENT_TYPE (db_get_client_type ())) + { + return; + } +#endif + + pl_server_manager = new cubpl::server_manager (db_name); + pl_server_manager->start (); +} + +void +pl_server_destroy () +{ + if (pl_server_manager != nullptr) + { + delete pl_server_manager; + pl_server_manager = nullptr; + } +} + +void +pl_server_wait_for_ready () +{ + if (pl_server_manager) + { + pl_server_manager->wait_for_server_ready (); + } +} + +PL_CONNECTION_POOL *get_connection_pool () +{ + if (pl_server_manager) + { + return pl_server_manager->get_connection_pool (); + } + else + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_RUNNING_JVM, 0); + return nullptr; + } +} diff --git a/src/sp/pl_sr.h b/src/sp/pl_sr.h new file mode 100644 index 00000000000..a2f21530542 --- /dev/null +++ b/src/sp/pl_sr.h @@ -0,0 +1,47 @@ +/* + * Copyright 2008 Search Solution Corporation + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +/* + * pl_sr.h - PL Server Module Header + * + * Note: + */ + +#ifndef _PL_SR_H_ +#define _PL_SR_H_ + +#include +#include + +#include "porting.h" +#include "thread_compat.hpp" +#include "pl_connection.hpp" + +extern EXPORT_IMPORT void pl_server_init (const char *db_name); +extern EXPORT_IMPORT void pl_server_destroy (); +extern EXPORT_IMPORT void pl_server_wait_for_ready (); + +extern EXPORT_IMPORT PL_CONNECTION_POOL *get_connection_pool (); + +extern EXPORT_IMPORT int pl_start_jvm_server (const char *server_name, const char *path, int port_number); +extern EXPORT_IMPORT int pl_server_port (void); +extern EXPORT_IMPORT int pl_server_port_from_info (void); +extern EXPORT_IMPORT int pl_jvm_is_loaded (void); + +#endif /* _PL_SR_H_ */ diff --git a/src/sp/jsp_sr.c b/src/sp/pl_sr_jvm.cpp similarity index 68% rename from src/sp/jsp_sr.c rename to src/sp/pl_sr_jvm.cpp index 5082ae703d8..4ead4ef03ce 100644 --- a/src/sp/jsp_sr.c +++ b/src/sp/pl_sr_jvm.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008 Search Solution Corporation + * * Copyright 2016 CUBRID Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,11 +17,9 @@ */ /* - * jsp_sr.c - Java Stored Procedure Server Module Source + * pl_sr_jvm.cpp - PL Server Module Source related to setup JVM */ -#ident "$Id$" - #include "config.h" #if defined(WINDOWS) @@ -42,9 +40,9 @@ #include #include -#include "jsp_sr.h" -#include "jsp_file.h" -#include "jsp_comm.h" +#include "pl_sr.h" +#include "pl_file.h" +#include "pl_comm.h" #include "boot_sr.h" #include "environment_variable.h" @@ -52,13 +50,11 @@ #include "release_string.h" #include "memory_alloc.h" #include "error_manager.h" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" -#if defined(sparc) -#define JVM_LIB_PATH "jre/lib/sparc/client" -#define JVM_LIB_PATH_JDK11 "lib/server" -#elif defined(WINDOWS) +#if defined(WINDOWS) #if __WORDSIZE == 32 #define JVM_LIB_PATH_JDK "jre\\bin\\client" #define JVM_LIB_PATH_JRE "bin\\client" @@ -68,42 +64,16 @@ #define JVM_LIB_PATH_JRE "bin\\server" #define JVM_LIB_PATH_JDK11 "bin\\server" #endif -#elif defined(HPUX) && defined(IA64) -#define JVM_LIB_PATH "jre/lib/IA64N/hotspot" -#define JVM_LIB_PATH_JDK11 "lib/IA64N/server" -#elif defined(HPUX) && !defined(IA64) -#define JVM_LIB_PATH "jre/lib/PA_RISC2.0/hotspot" -#define JVM_LIB_PATH_JDK11 "lib/PA_RISC2.0/server" -#elif defined(AIX) -#if __WORDSIZE == 32 -#define JVM_LIB_PATH "jre/bin/classic" -#define JVM_LIB_PATH_JDK11 "lib/server" -#elif __WORDSIZE == 64 -#define JVM_LIB_PATH "jre/lib/ppc64/classic" -#define JVM_LIB_PATH_JDK11 "lib/server" -#endif -#elif defined(__i386) || defined(__x86_64) -#if __WORDSIZE == 32 -#define JVM_LIB_PATH "jre/lib/i386/client" -#define JVM_LIB_PATH_JDK11 "lib/server" #else #define JVM_LIB_PATH "jre/lib/amd64/server" #define JVM_LIB_PATH_JDK11 "lib/server" #endif -#else /* ETC */ -#define JVM_LIB_PATH "" -#define JVM_LIB_PATH_JDK11 "" -#endif /* ETC */ -#if !defined(WINDOWS) -#if defined(AIX) -#define JVM_LIB_FILE "libjvm.so" -#elif defined(HPUX) && !defined(IA64) -#define JVM_LIB_FILE "libjvm.sl" -#else /* not AIX , not ( HPUX && (not IA64)) */ +#if defined(WINDOWS) +#define JVM_LIB_FILE "libjvm.dll" +#else #define JVM_LIB_FILE "libjvm.so" -#endif /* not AIX , not ( HPUX && (not IA64)) */ -#endif /* !WINDOWS */ +#endif #if defined(WINDOWS) #define REGKEY_JAVA "Software\\JavaSoft\\Java Runtime Environment" @@ -145,9 +115,7 @@ typedef jint (*CREATE_VM_FUNC) (JavaVM **, void **, void *); static JavaVM *jvm = NULL; static jint sp_port = -1; -// *INDENT-OFF* static std::string err_msgs; -// *INDENT-ON* #if defined(WINDOWS) int get_java_root_path (char *path); @@ -158,9 +126,10 @@ extern PfnDliHook __pfnDliNotifyHook2 = delay_load_hook; extern PfnDliHook __pfnDliFailureHook2 = delay_load_hook; #else /* WINDOWS */ -static void *jsp_get_create_java_vm_function_ptr (void); +static void *pl_get_create_java_vm_function_ptr (void); #endif /* !WINDOWS */ + #if defined(WINDOWS) /* @@ -249,86 +218,86 @@ delay_load_hook (unsigned dliNotify, PDelayLoadInfo pdli) switch (dliNotify) { case dliFailLoadLib: - { - char *java_home = NULL, *jvm_path = NULL, *tmp = NULL, *tail; - void *libVM = NULL; + { + char *java_home = NULL, *jvm_path = NULL, *tmp = NULL, *tail; + void *libVM = NULL; - jvm_path = getenv ("JVM_PATH"); - java_home = getenv ("JAVA_HOME"); + jvm_path = getenv ("JVM_PATH"); + java_home = getenv ("JAVA_HOME"); - if (jvm_path) - { - err_msgs.append ("\n\tFailed to load libjvm from 'JVM_PATH' environment variable: "); - err_msgs.append ("\n\t\t"); - err_msgs.append (jvm_path); - - libVM = LoadLibrary (jvm_path); - if (libVM) - { - fp = (FARPROC) (HMODULE) libVM; - return fp; - } - } - else - { - err_msgs.append ("\n\tFailed to get 'JVM_PATH' environment variable"); - } + if (jvm_path) + { + err_msgs.append ("\n\tFailed to load libjvm from 'JVM_PATH' environment variable: "); + err_msgs.append ("\n\t\t"); + err_msgs.append (jvm_path); + + libVM = LoadLibrary (jvm_path); + if (libVM) + { + fp = (FARPROC) (HMODULE) libVM; + return fp; + } + } + else + { + err_msgs.append ("\n\tFailed to get 'JVM_PATH' environment variable"); + } - tail = JVM_LIB_PATH_JDK; - if (java_home == NULL) - { - tmp = (char *) malloc (BUF_SIZE); - if (tmp) - { - if (get_java_root_path (tmp)) - { - java_home = tmp; - tail = JVM_LIB_PATH_JRE; - } - } - } + tail = JVM_LIB_PATH_JDK; + if (java_home == NULL) + { + tmp = (char *) malloc (BUF_SIZE); + if (tmp) + { + if (get_java_root_path (tmp)) + { + java_home = tmp; + tail = JVM_LIB_PATH_JRE; + } + } + } - if (java_home) - { - err_msgs.append ("\n\tFailed to load libjvm from 'JAVA_HOME' environment variable: "); + if (java_home) + { + err_msgs.append ("\n\tFailed to load libjvm from 'JAVA_HOME' environment variable: "); - char jvm_lib_path[BUF_SIZE]; - sprintf (jvm_lib_path, "%s\\%s\\jvm.dll", java_home, tail); + char jvm_lib_path[BUF_SIZE]; + sprintf (jvm_lib_path, "%s\\%s\\jvm.dll", java_home, tail); - err_msgs.append ("\n\t\t"); - err_msgs.append (jvm_lib_path); + err_msgs.append ("\n\t\t"); + err_msgs.append (jvm_lib_path); - libVM = LoadLibrary (jvm_lib_path); + libVM = LoadLibrary (jvm_lib_path); - if (libVM) - { - fp = (FARPROC) (HMODULE) libVM; - } - else - { - tail = JVM_LIB_PATH_JDK11; + if (libVM) + { + fp = (FARPROC) (HMODULE) libVM; + } + else + { + tail = JVM_LIB_PATH_JDK11; - memset (jvm_lib_path, BUF_SIZE, 0); - sprintf (jvm_lib_path, "%s\\%s\\jvm.dll", java_home, tail); + memset (jvm_lib_path, BUF_SIZE, 0); + sprintf (jvm_lib_path, "%s\\%s\\jvm.dll", java_home, tail); - err_msgs.append ("\n\t\t"); - err_msgs.append (jvm_lib_path); + err_msgs.append ("\n\t\t"); + err_msgs.append (jvm_lib_path); - libVM = LoadLibrary (jvm_lib_path); - fp = (FARPROC) (HMODULE) libVM; - } - } - else - { - err_msgs.append ("\n\tFailed to get 'JAVA_HOME' environment variable"); - } + libVM = LoadLibrary (jvm_lib_path); + fp = (FARPROC) (HMODULE) libVM; + } + } + else + { + err_msgs.append ("\n\tFailed to get 'JAVA_HOME' environment variable"); + } - if (tmp) - { - free_and_init (tmp); - } - } - break; + if (tmp) + { + free_and_init (tmp); + } + } + break; default: break; @@ -365,14 +334,14 @@ delay_load_dll_exception_filter (PEXCEPTION_POINTERS pep) #else /* WINDOWS */ /* - * jsp_get_create_java_vm_func_ptr + * pl_get_create_java_vm_func_ptr * return: return java vm function pointer * * Note: */ static void * -jsp_get_create_java_vm_function_ptr () +pl_get_create_java_vm_function_ptr () { void *libVM_p = NULL; @@ -440,26 +409,26 @@ jsp_get_create_java_vm_function_ptr () /* - * jsp_create_java_vm + * pl_create_java_vm * return: create java vm * * Note: */ static int -jsp_create_java_vm (JNIEnv ** env_p, JavaVMInitArgs * vm_arguments) +pl_create_java_vm (JNIEnv **env_p, JavaVMInitArgs *vm_arguments) { int res; #if defined(WINDOWS) __try - { - res = JNI_CreateJavaVM (&jvm, (void **) env_p, vm_arguments); - } + { + res = JNI_CreateJavaVM (&jvm, (void **) env_p, vm_arguments); + } __except (delay_load_dll_exception_filter (GetExceptionInformation ())) - { - res = -1; - } + { + res = -1; + } #else /* WINDOWS */ - CREATE_VM_FUNC create_vm_func = (CREATE_VM_FUNC) jsp_get_create_java_vm_function_ptr (); + CREATE_VM_FUNC create_vm_func = (CREATE_VM_FUNC) pl_get_create_java_vm_function_ptr (); if (create_vm_func) { res = (*create_vm_func) (&jvm, (void **) env_p, (void *) vm_arguments); @@ -475,14 +444,12 @@ jsp_create_java_vm (JNIEnv ** env_p, JavaVMInitArgs * vm_arguments) } /* - * jsp_tokenize_jvm_options + * pl_tokenize_jvm_options * return: tokenized array of string * */ - -// *INDENT-OFF* static std::vector -jsp_tokenize_jvm_options (char *opt_str) +pl_tokenize_jvm_options (char *opt_str) { std::string str (opt_str); std::istringstream iss (str); @@ -491,10 +458,58 @@ jsp_tokenize_jvm_options (char *opt_str) std::istream_iterator (), std::back_inserter (options)); return options; } -// *INDENT-ON* /* - * jsp_start_server - + * pl_jvm_options + * return: jvm options + * + */ +static std::vector +pl_jvm_options () +{ + char buffer[PATH_MAX]; + + envvar_javadir_file (buffer, PATH_MAX, ""); + std::string pl_file_path (buffer); + + std::vector options; + +#ifndef NDEBUG + // enable assertions in PL Server + options.push_back ("-ea"); // must be the first option in order not to override ones specified by the user +#endif // !NDEBUG + + // defaults + options.push_back ("-Djava.awt.headless=true"); + options.push_back ("-Dfile.encoding=UTF-8"); + + // CBRD-25364: Prevent JVM crash caused by libzip + // Added the following option as a default until the minimum JDK version is upgraded + options.push_back ("-Dsun.zip.disableMemoryMapping=true"); + + // + options.push_back ("-Djava.class.path=" + pl_file_path + "pl_server.jar"); + options.push_back ("-Djava.util.logging.config.file=" + pl_file_path + "logging.properties"); + + int debug_port = prm_get_integer_value (PRM_ID_JAVA_STORED_PROCEDURE_DEBUG); + if (debug_port != -1) + { + options.push_back ("-Xdebug"); + options.push_back ("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=" + std::to_string (debug_port)); + } + + char *jvm_opt_sysprm = (char *) prm_get_string_value (PRM_ID_JAVA_STORED_PROCEDURE_JVM_OPTIONS); + if (jvm_opt_sysprm != NULL) + { + std::vector ext_opts = pl_tokenize_jvm_options (jvm_opt_sysprm); + options.insert (options.end(), ext_opts.begin(), ext_opts.end()); + } + + return options; +} + +/* + * pl_start_jvm_server - * return: Error Code * db_name(in): db name * path(in): path @@ -503,7 +518,7 @@ jsp_tokenize_jvm_options (char *opt_str) */ int -jsp_start_server (const char *db_name, const char *path, int port) +pl_start_jvm_server (const char *db_name, const char *path, int port) { jint res; jclass cls, string_cls; @@ -513,21 +528,11 @@ jsp_start_server (const char *db_name, const char *path, int port) jobjectArray args; JavaVMInitArgs vm_arguments; JavaVMOption *options; - int vm_n_default_options = 2; - int vm_n_ext_options = 0; - char classpath[PATH_MAX + 32] = { 0 }; - char logging_prop[PATH_MAX + 32] = { 0 }; - char option_debug[70]; - char debug_flag[] = "-Xdebug"; - char debug_jdwp[] = "-agentlib:jdwp=transport=dt_socket,server=y,address=%d,suspend=n"; + int vm_n_options = 0; const char *envroot; const char *uds_path; - char jsp_file_path[PATH_MAX]; - char port_str[6] = { 0 }; char *loc_p, *locale; - char *jvm_opt_sysprm = NULL; - int debug_port = -1; - const bool is_uds_mode = (port == JAVASP_PORT_UDS_MODE); + const bool is_uds_mode = (port == PL_PORT_UDS_MODE); { if (jvm != NULL) { @@ -535,63 +540,26 @@ jsp_start_server (const char *db_name, const char *path, int port) } envroot = envvar_root (); + uds_path = (is_uds_mode) ? pl_get_socket_file_path (db_name) : ""; - if (is_uds_mode) - { - uds_path = jsp_get_socket_file_path (db_name); - } - else - { - uds_path = ""; - } - - snprintf (classpath, sizeof (classpath) - 1, "-Djava.class.path=%s", - envvar_javadir_file (jsp_file_path, PATH_MAX, "pl_server.jar")); - - snprintf (logging_prop, sizeof (logging_prop) - 1, "-Djava.util.logging.config.file=%s", - envvar_javadir_file (jsp_file_path, PATH_MAX, "logging.properties")); - - debug_port = prm_get_integer_value (PRM_ID_JAVA_STORED_PROCEDURE_DEBUG); - if (debug_port != -1) - { - vm_n_default_options += 2; /* set debug flag and debugging port */ - } + std::vector opts = pl_jvm_options (); - jvm_opt_sysprm = (char *) prm_get_string_value (PRM_ID_JAVA_STORED_PROCEDURE_JVM_OPTIONS); - // *INDENT-OFF* - std::vector opts = jsp_tokenize_jvm_options (jvm_opt_sysprm); -#ifndef NDEBUG - // enable assertions in PL Server - opts.insert(opts.begin(), "-ea"); // must be the first option in order not to override ones specified by the user -#endif // !NDEBUG - // *INDENT-ON* - vm_n_ext_options += (int) opts.size (); - options = new JavaVMOption[vm_n_default_options + vm_n_ext_options]; + vm_n_options = (int) opts.size (); + options = new JavaVMOption[vm_n_options]; if (options == NULL) { er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 0); goto exit; } - int ext_idx = vm_n_default_options; - options[0].optionString = classpath; - options[1].optionString = logging_prop; - if (debug_port != -1) - { - snprintf (option_debug, sizeof (option_debug) - 1, debug_jdwp, debug_port); - options[2].optionString = debug_flag; - options[3].optionString = option_debug; - } - + int idx = 0; for (auto it = opts.begin (); it != opts.end (); ++it) { - // *INDENT-OFF* - options[ext_idx++].optionString = const_cast (it->c_str ()); - // *INDENT-ON* + options[idx++].optionString = const_cast (it->c_str ()); } vm_arguments.version = JNI_VERSION_1_6; - vm_arguments.nOptions = vm_n_default_options + vm_n_ext_options; + vm_arguments.nOptions = vm_n_options; vm_arguments.options = options; vm_arguments.ignoreUnrecognized = JNI_TRUE; @@ -602,10 +570,8 @@ jsp_start_server (const char *db_name, const char *path, int port) locale = strdup (loc_p); } - res = jsp_create_java_vm (&env_p, &vm_arguments); - // *INDENT-OFF* - delete[] options; - // *INDENT-ON* + res = pl_create_java_vm (&env_p, &vm_arguments); + delete[] options; #if !defined(WINDOWS) if (er_has_error ()) @@ -685,6 +651,7 @@ jsp_start_server (const char *db_name, const char *path, int port) goto exit; } + char port_str[6] = { 0 }; sprintf (port_str, "%d", port); jstr_port = JVM_NewStringUTF (env_p, port_str); if (jstr_port == NULL) @@ -737,8 +704,8 @@ jsp_start_server (const char *db_name, const char *path, int port) } /* - * jsp_server_port - * return: if jsp is disabled return -2 (JAVASP_PORT_DISABLED) + * pl_server_port + * return: if jsp is disabled return -2 (PL_PORT_DISABLED) * else if jsp is UDS mode return -1 * else return a port (TCP mode) * @@ -746,38 +713,38 @@ jsp_start_server (const char *db_name, const char *path, int port) */ int -jsp_server_port (void) +pl_server_port (void) { return sp_port; } /* - * jsp_server_port_from_info - * return: if jsp is disabled return -2 (JAVASP_PORT_DISABLED) + * pl_server_port_from_info + * return: if jsp is disabled return -2 (PL_PORT_DISABLED) * else if jsp is UDS mode return -1 * else return a port (TCP mode) - * + * * * Note: */ int -jsp_server_port_from_info (void) +pl_server_port_from_info (void) { -#if defined (SA_MODE) - return sp_port; -#else - // check $CUBRID/var/javasp_.info -// *INDENT-OFF* - JAVASP_SERVER_INFO jsp_info {-1, -1}; -// *INDENT-ON* - javasp_read_info (boot_db_name (), jsp_info); - return sp_port = jsp_info.port; +#if defined (SERVER_MODE) + // check $CUBRID/var/pl_.info + if (sp_port != PL_PORT_DISABLED) + { + PL_SERVER_INFO pl_info {-1, -1}; + pl_read_info (boot_db_name (), pl_info); + sp_port = pl_info.port; + } #endif + return sp_port; } /* - * jsp_jvm_is_loaded + * pl_jvm_is_loaded * return: if disable jsp function and return false * enable jsp function and return not false * @@ -785,7 +752,7 @@ jsp_server_port_from_info (void) */ int -jsp_jvm_is_loaded (void) +pl_jvm_is_loaded (void) { return jvm != NULL; } diff --git a/src/method/method_compile_def.cpp b/src/sp/pl_struct_compile.cpp similarity index 90% rename from src/method/method_compile_def.cpp rename to src/sp/pl_struct_compile.cpp index 66c0cd0572b..d6f6ecdb5ea 100644 --- a/src/method/method_compile_def.cpp +++ b/src/sp/pl_struct_compile.cpp @@ -16,22 +16,57 @@ * */ -#include "method_compile_def.hpp" +#include "pl_struct_compile.hpp" #include "byte_order.h" #include "connection_support.h" #include "dbtype.h" /* db_value_* */ -#include "method_def.hpp" + #include "method_struct_value.hpp" +#include "sp_constants.hpp" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" -namespace cubmethod +namespace cubpl { ////////////////////////////////////////////////////////////////////////// // compile info ////////////////////////////////////////////////////////////////////////// - compile_info::compile_info () + +#define COMPILE_REQUEST_PACKER_ARGS() \ + code, owner, mode + + compile_request::compile_request () + : code {} + , owner {} + , mode {} + { + // + } + + void + compile_request::pack (cubpacking::packer &serializator) const + { + serializator.pack_all (COMPILE_REQUEST_PACKER_ARGS ()); + } + + size_t + compile_request::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const + { + return serializator.get_all_packed_size_starting_offset (start_offset, + COMPILE_REQUEST_PACKER_ARGS ()); + } + + void + compile_request::unpack (cubpacking::unpacker &deserializator) + { + deserializator.unpack_all (COMPILE_REQUEST_PACKER_ARGS ()); + } + +// + + compile_response::compile_response () : err_code (-1) , err_line (0) , err_column (0) @@ -40,7 +75,7 @@ namespace cubmethod } void - compile_info::pack (cubpacking::packer &serializator) const + compile_response::pack (cubpacking::packer &serializator) const { serializator.pack_int (err_code); if (err_code < 0) @@ -55,11 +90,17 @@ namespace cubmethod serializator.pack_string (register_stmt); serializator.pack_string (class_name); serializator.pack_string (java_signature); + + serializator.pack_int (compiled_type); + if (compiled_type >= 0) + { + serializator.pack_string (compiled_code); + } } } size_t - compile_info::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const + compile_response::get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const { size_t size = serializator.get_packed_int_size (start_offset); // err_code @@ -75,13 +116,19 @@ namespace cubmethod size += serializator.get_packed_string_size (register_stmt, size); // register_stmt size += serializator.get_packed_string_size (class_name, size); // class_name size += serializator.get_packed_string_size (java_signature, size); // java_signature + + size += serializator.get_packed_int_size (size); // compiled_type + if (compiled_type >= 0) + { + size += serializator.get_packed_string_size (compiled_code, size); // compiled_code + } } return size; } void - compile_info::unpack (cubpacking::unpacker &deserializator) + compile_response::unpack (cubpacking::unpacker &deserializator) { deserializator.unpack_int (err_code); if (err_code < 0) @@ -96,6 +143,12 @@ namespace cubmethod deserializator.unpack_string (register_stmt); deserializator.unpack_string (class_name); deserializator.unpack_string (java_signature); + + deserializator.unpack_int (compiled_type); + if (compiled_type >= 0) + { + deserializator.unpack_string (compiled_code); + } } } @@ -322,7 +375,7 @@ namespace cubmethod if (!DB_IS_NULL (&value)) { - dbvalue_java sp_val; + cubmethod::dbvalue_java sp_val; serializator.pack_int (1); sp_val.value = (DB_VALUE *) &value; sp_val.pack (serializator); @@ -348,7 +401,7 @@ namespace cubmethod size += serializator.get_packed_int_size (size); // value is null if (!DB_IS_NULL (&value)) { - dbvalue_java sp_val; + cubmethod::dbvalue_java sp_val; sp_val.value = (DB_VALUE *) &value; size += sp_val.get_packed_size (serializator, size); } @@ -373,7 +426,7 @@ namespace cubmethod if (value_is_null == 1) { - dbvalue_java value_unpacker; + cubmethod::dbvalue_java value_unpacker; value_unpacker.value = &value; value_unpacker.unpack (deserializator); } diff --git a/src/method/method_compile_def.hpp b/src/sp/pl_struct_compile.hpp similarity index 85% rename from src/method/method_compile_def.hpp rename to src/sp/pl_struct_compile.hpp index a5703364f1f..3d3d0b36ab3 100644 --- a/src/method/method_compile_def.hpp +++ b/src/sp/pl_struct_compile.hpp @@ -17,11 +17,11 @@ */ // -// method_compile_def.hpp - define structures used by method feature +// pl_struct_compile.hpp - define structures used by method feature // -#ifndef _METHOD_COMPILE_DEF_HPP_ -#define _METHOD_COMPILE_DEF_HPP_ +#ifndef _PL_STRUCT_COMPILE_HPP_ +#define _PL_STRUCT_COMPILE_HPP_ #include "mem_block.hpp" #include "packer.hpp" @@ -33,13 +33,26 @@ #include #include -namespace cubmethod +namespace cubpl { struct pl_parameter_info; - struct EXPORT_IMPORT compile_info : public cubpacking::packable_object + struct EXPORT_IMPORT compile_request : public cubpacking::packable_object { - compile_info (); + compile_request (); + + std::string code; + std::string owner; + std::string mode; /* for debugging : compile configs such as verbose */ + + void pack (cubpacking::packer &serializator) const override; + void unpack (cubpacking::unpacker &deserializator) override; + size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; + }; + + struct EXPORT_IMPORT compile_response : public cubpacking::packable_object + { + compile_response (); void pack (cubpacking::packer &serializator) const override; void unpack (cubpacking::unpacker &deserializator) override; @@ -54,6 +67,9 @@ namespace cubmethod std::string register_stmt; std::string class_name; std::string java_signature; + + int compiled_type; + std::string compiled_code; }; struct EXPORT_IMPORT sql_semantics : public cubpacking::packable_object @@ -68,7 +84,7 @@ namespace cubmethod int sql_type; std::string rewritten_query; - std::vector columns; + std::vector columns; std::vector hvs; std::vector into_vars; }; @@ -180,7 +196,7 @@ namespace cubmethod void unpack (cubpacking::unpacker &deserializator) override; size_t get_packed_size (cubpacking::packer &serializator, std::size_t start_offset) const override; - column_info c_info; + cubmethod::column_info c_info; }; struct EXPORT_IMPORT global_semantics_response : public cubpacking::packable_object @@ -193,6 +209,7 @@ namespace cubmethod }; } -using PLCSQL_COMPILE_INFO = cubmethod::compile_info; +using PLCSQL_COMPILE_REQUEST = cubpl::compile_request; +using PLCSQL_COMPILE_RESPONSE = cubpl::compile_response; -#endif //_METHOD_COMPILE_DEF_HPP_ +#endif //_PL_STRUCT_COMPILE_HPP_ diff --git a/src/sp/sp_catalog.cpp b/src/sp/sp_catalog.cpp new file mode 100644 index 00000000000..4caaad95373 --- /dev/null +++ b/src/sp/sp_catalog.cpp @@ -0,0 +1,1023 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * sp_catalog.cpp - Implement stored procedure related system catalog's row sturcture and initializer +*/ + +#include "sp_catalog.hpp" + +#include + +#include "jsp_cl.h" +#include "authenticate.h" +#include "object_domain.h" +#include "object_primitive.h" +#include "object_representation.h" +#include "db.h" +#include "object_accessor.h" +#include "set_object.h" +#include "locator_cl.h" +#include "transaction_cl.h" +#include "schema_manager.h" +#include "dbtype.h" + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" + +// memory representation of built-in stored procedures +static std::vector sp_builtin_definition; + +static const std::vector sp_entry_names +{ + SP_ATTR_UNIQUE_NAME, + SP_ATTR_NAME, + SP_ATTR_SP_TYPE, + SP_ATTR_RETURN_TYPE, + SP_ATTR_ARG_COUNT, + SP_ATTR_ARGS, + SP_ATTR_LANG, + SP_ATTR_PKG, + SP_ATTR_IS_SYSTEM_GENERATED, + SP_ATTR_TARGET_CLASS, + SP_ATTR_TARGET_METHOD, + SP_ATTR_DIRECTIVE, + SP_ATTR_OWNER, + SP_ATTR_COMMENT +}; + +static const std::vector sp_args_entry_names +{ + SP_ATTR_SP_OF, + SP_ATTR_PKG, + SP_ATTR_INDEX_OF_NAME, + SP_ATTR_IS_SYSTEM_GENERATED, + SP_ATTR_ARG_NAME, + SP_ATTR_DATA_TYPE, + SP_ATTR_MODE, + SP_ATTR_DEFAULT_VALUE, + SP_ATTR_IS_OPTIONAL, + SP_ATTR_COMMENT +}; + +static int sp_add_stored_procedure_internal (SP_INFO &info, bool has_savepoint); +static int sp_builtin_init (); + +// TODO +static int sp_builtin_init () +{ + if (sp_builtin_definition.size () > 0) + { + // already initialized + return 0; + } + + sp_info v; + sp_arg_info a; + + // common + v.is_system_generated = true; + v.lang = SP_LANG_PLCSQL; + v.owner = Au_public_user; + v.comment = ""; + v.directive = SP_DIRECTIVE_RIGHTS_OWNER; + v.target_class = "com.cubrid.plcsql.builtin.DBMS_OUTPUT"; + + a.is_system_generated = true; + + // DBMS_OUTPUT.enable + v.unique_name = "public.dbms_output.enable"; + v.sp_name = "enable"; + v.pkg_name = "DBMS_OUTPUT"; + v.sp_type = SP_TYPE_PROCEDURE; + v.return_type = DB_TYPE_NULL; + v.target_method = "enable(int)"; + + // arg(0) of enable + a.sp_name = v.sp_name; + a.pkg_name = "DBMS_OUTPUT"; + a.index_of = 0; + a.arg_name = "s"; + a.data_type = DB_TYPE_INTEGER; + a.mode = SP_MODE_IN; + a.comment = ""; + + v.args.push_back (a); + + // + sp_builtin_definition.push_back (v); + v.args.clear (); + // + + // DBMS_OUTPUT.disable + v.unique_name = "public.dbms_output.disable"; + v.sp_name = "disable"; + v.pkg_name = "DBMS_OUTPUT"; + v.sp_type = SP_TYPE_PROCEDURE; + v.return_type = DB_TYPE_NULL; + v.target_method = "disable()"; + + // + sp_builtin_definition.push_back (v); + v.args.clear (); + // + + // DBMS_OUTPUT.put + v.unique_name = "public.dbms_output.put"; + v.sp_name = "put"; + v.pkg_name = "DBMS_OUTPUT"; + v.sp_type = SP_TYPE_PROCEDURE; + v.return_type = DB_TYPE_NULL; + v.target_method = "put(java.lang.String)"; + + // arg(0) of put + a.sp_name = v.sp_name; + a.pkg_name = "DBMS_OUTPUT"; + a.index_of = 0; + a.arg_name = "str"; + a.data_type = DB_TYPE_STRING; + a.mode = SP_MODE_IN; + a.comment = ""; + + v.args.push_back (a); + + // + sp_builtin_definition.push_back (v); + v.args.clear (); + // + + // DBMS_OUTPUT.put_line + v.unique_name = "public.dbms_output.put_line"; + v.sp_name = "put_line"; + v.pkg_name = "DBMS_OUTPUT"; + v.sp_type = SP_TYPE_PROCEDURE; + v.return_type = DB_TYPE_NULL; + v.target_method = "putLine(java.lang.String)"; + + // arg(0) of put_line + a.sp_name = v.sp_name; + a.pkg_name = "DBMS_OUTPUT"; + a.index_of = 0; + a.arg_name = "str"; + a.data_type = DB_TYPE_STRING; + a.mode = SP_MODE_IN; + a.comment = ""; + + v.args.push_back (a); + + // + sp_builtin_definition.push_back (v); + v.args.clear (); + // + + // DBMS_OUTPUT.new_line + v.unique_name = "public.dbms_output.new_line"; + v.sp_name = "new_line"; + v.pkg_name = "DBMS_OUTPUT"; + v.sp_type = SP_TYPE_PROCEDURE; + v.return_type = DB_TYPE_NULL; + v.target_method = "newLine()"; + + // + sp_builtin_definition.push_back (v); + v.args.clear (); + // + + // DBMS_OUTPUT.get_line + v.unique_name = "public.dbms_output.get_line"; + v.sp_name = "get_line"; + v.pkg_name = "DBMS_OUTPUT"; + v.sp_type = SP_TYPE_PROCEDURE; + v.return_type = DB_TYPE_NULL; + v.target_method = "getLine(java.lang.String[], int[])"; + + // arg(0) of get_line + a.sp_name = v.sp_name; + a.pkg_name = "DBMS_OUTPUT"; + a.index_of = 0; + a.arg_name = "line"; + a.data_type = DB_TYPE_STRING; + a.mode = SP_MODE_OUT; + a.comment = ""; + + v.args.push_back (a); + + // arg(1) of get_line + a.sp_name = v.sp_name; + a.pkg_name = "DBMS_OUTPUT"; + a.index_of = 1; + a.arg_name = "status"; + a.data_type = DB_TYPE_INTEGER; + a.mode = SP_MODE_OUT; + a.comment = ""; + + v.args.push_back (a); + + // + sp_builtin_definition.push_back (v); + v.args.clear (); + // + + // DBMS_OUTPUT.get_lines + v.unique_name = "public.dbms_output.get_lines"; + v.sp_name = "get_lines"; + v.pkg_name = "DBMS_OUTPUT"; + v.sp_type = SP_TYPE_PROCEDURE; + v.return_type = DB_TYPE_NULL; + v.target_method = "getLines(java.lang.String[], int[])"; + + // arg(0) of get_lines + a.sp_name = v.sp_name; + a.pkg_name = "DBMS_OUTPUT"; + a.index_of = 0; + a.arg_name = "lines"; + a.data_type = DB_TYPE_STRING; + a.mode = SP_MODE_OUT; + a.comment = ""; + + v.args.push_back (a); + + // arg(1) of get_line + a.sp_name = v.sp_name; + a.pkg_name = "DBMS_OUTPUT"; + a.index_of = 1; + a.arg_name = "cnt"; + a.data_type = DB_TYPE_INTEGER; + a.mode = SP_MODE_OUT; + a.comment = ""; + + v.args.push_back (a); + + // + sp_builtin_definition.push_back (v); + v.args.clear (); + // + + return sp_builtin_definition.size (); +} + +sp_entry::sp_entry (int size) +{ + vals.resize (size); + for (DB_VALUE &val : vals) + { + db_make_null (&val); + } +} + +sp_entry::~sp_entry () +{ + for (DB_VALUE &val : vals) + { + db_value_clear (&val); + } +} + +int sp_builtin_install () +{ + (void) sp_builtin_init (); + + int error = NO_ERROR; + for (sp_info &info : sp_builtin_definition) + { + error = sp_add_stored_procedure_internal (info, false); + assert (error == NO_ERROR); + } + return error; +} + +int +sp_check_param_type_supported (DB_TYPE domain_type, SP_MODE_ENUM mode) +{ + switch (domain_type) + { + case DB_TYPE_INTEGER: + case DB_TYPE_FLOAT: + case DB_TYPE_DOUBLE: + case DB_TYPE_STRING: + case DB_TYPE_OBJECT: + case DB_TYPE_SET: + case DB_TYPE_MULTISET: + case DB_TYPE_SEQUENCE: + case DB_TYPE_TIME: + case DB_TYPE_TIMESTAMP: + case DB_TYPE_DATE: + case DB_TYPE_MONETARY: + case DB_TYPE_SHORT: + case DB_TYPE_NUMERIC: + case DB_TYPE_CHAR: + case DB_TYPE_BIGINT: + case DB_TYPE_DATETIME: + return NO_ERROR; + break; + + case DB_TYPE_RESULTSET: + if (mode != SP_MODE_OUT) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_CANNOT_INPUT_RESULTSET, 0); + } + break; + + default: + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_SUPPORTED_ARG_TYPE, 1, pr_type_name (domain_type)); + break; + } + + return er_errid (); +} + +int +sp_add_stored_procedure (SP_INFO &info) +{ + return sp_add_stored_procedure_internal (info, true); +} + +static int +sp_add_stored_procedure_internal (SP_INFO &info, bool has_savepoint) +{ + DB_OBJECT *classobj_p, *object_p, *sp_args_obj; + DB_OTMPL *obt_p = NULL; + DB_VALUE value; + DB_SET *param = NULL; + MOP *mop_list = NULL; + int save, err; + + AU_DISABLE (save); + + { + classobj_p = db_find_class (SP_CLASS_NAME); + if (classobj_p == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + if (has_savepoint) + { + err = tran_system_savepoint (SAVEPOINT_ADD_STORED_PROC); + if (err != NO_ERROR) + { + has_savepoint = false; + goto error; + } + } + + obt_p = dbt_create_object_internal (classobj_p); + if (!obt_p) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + /* unique_name */ + db_make_string (&value, info.unique_name.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_UNIQUE_NAME, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + /* sp_name */ + db_make_string (&value, info.sp_name.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_NAME, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.sp_type); + err = dbt_put_internal (obt_p, SP_ATTR_SP_TYPE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + err = jsp_check_return_type_supported (info.return_type); + if (err == ER_SP_CANNOT_RETURN_RESULTSET) + { + // ignore this error here + err = NO_ERROR; + er_clear (); + } + else if (err != NO_ERROR) + { + err = er_errid (); + goto error; + } + + db_make_int (&value, (int) info.return_type); + err = dbt_put_internal (obt_p, SP_ATTR_RETURN_TYPE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + if (!info.pkg_name.empty ()) + { + sp_normalize_name (info.pkg_name); + db_make_string (&value, info.pkg_name.data ()); + } + err = dbt_put_internal (obt_p, SP_ATTR_PKG, &value); + pr_clear_value (&value); + + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.is_system_generated ? 1 : 0); + err = dbt_put_internal (obt_p, SP_ATTR_IS_SYSTEM_GENERATED, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.directive); + err = dbt_put_internal (obt_p, SP_ATTR_DIRECTIVE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + // args (_db_stored_procedure_args) begin + param = set_create_sequence (0); + if (param == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + mop_list = (MOP *) malloc (info.args.size() * sizeof (MOP)); + + int i = 0; + for (sp_arg_info &arg: info.args) + { + DB_VALUE v; + + err = sp_check_param_type_supported (arg.data_type, arg.mode); + if (err != NO_ERROR) + { + goto error; + } + + arg.sp_name = info.sp_name; + arg.pkg_name = info.pkg_name; + + err = sp_add_stored_procedure_argument (&mop_list[i], arg); + if (err != NO_ERROR) + { + goto error; + } + + db_make_object (&v, mop_list[i]); + err = set_put_element (param, i++, &v); + pr_clear_value (&v); + + if (err != NO_ERROR) + { + goto error; + } + } + db_make_sequence (&value, param); + err = dbt_put_internal (obt_p, SP_ATTR_ARGS, &value); + pr_clear_value (&value); + param = NULL; + if (err != NO_ERROR) + { + goto error; + } + // args (_db_stored_procedure_args) end + + db_make_int (&value, (int) info.args.size ()); + err = dbt_put_internal (obt_p, SP_ATTR_ARG_COUNT, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.lang); + err = dbt_put_internal (obt_p, SP_ATTR_LANG, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_string (&value, info.target_class.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_TARGET_CLASS, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_string (&value, info.target_method.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_TARGET_METHOD, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_object (&value, info.owner); + err = dbt_put_internal (obt_p, SP_ATTR_OWNER, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + if (!info.comment.empty ()) + { + db_make_string (&value, info.comment.data ()); + } + err = dbt_put_internal (obt_p, SP_ATTR_COMMENT, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + object_p = dbt_finish_object (obt_p); + if (!object_p) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + obt_p = NULL; + + err = locator_flush_instance (object_p); + if (err != NO_ERROR) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + obj_delete (object_p); + goto error; + } + + // args (_db_stored_procedure_args) sp_of oid begin + for (i--; i >= 0; i--) + { + obt_p = dbt_edit_object (mop_list[i]); + if (!obt_p) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + db_make_object (&value, object_p); + err = dbt_put_internal (obt_p, SP_ATTR_SP_OF, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + sp_args_obj = dbt_finish_object (obt_p); + if (!sp_args_obj) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + obt_p = NULL; + + err = locator_flush_instance (sp_args_obj); + if (err != NO_ERROR) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + obj_delete (sp_args_obj); + goto error; + } + } + free (mop_list); + // args (_db_stored_procedure_args) sp_of oid end + } + + AU_ENABLE (save); + return NO_ERROR; + +error: + if (param) + { + set_free (param); + } + + if (obt_p) + { + dbt_abort_object (obt_p); + } + + if (has_savepoint) + { + tran_abort_upto_system_savepoint (SAVEPOINT_ADD_STORED_PROC); + } + + AU_ENABLE (save); + + return (er_errid () != NO_ERROR) ? er_errid () : ER_FAILED; +} + +int +sp_add_stored_procedure_argument (MOP *mop_p, SP_ARG_INFO &info) +{ + DB_OBJECT *classobj_p, *object_p; + DB_OTMPL *obt_p = NULL; + DB_VALUE value; + int save; + int err; + + db_make_null (&value); + AU_DISABLE (save); + + classobj_p = db_find_class (SP_ARG_CLASS_NAME); + if (classobj_p == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + obt_p = dbt_create_object_internal (classobj_p); + if (obt_p == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + if (!info.pkg_name.empty ()) + { + db_make_string (&value, info.pkg_name.data ()); + } + err = dbt_put_internal (obt_p, SP_ATTR_PKG, &value); + pr_clear_value (&value); + + if (err != NO_ERROR) + { + goto error; + } + + db_make_string (&value, info.arg_name.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_ARG_NAME, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.index_of); + err = dbt_put_internal (obt_p, SP_ATTR_INDEX_OF_NAME, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.is_system_generated ? 1 : 0); + err = dbt_put_internal (obt_p, SP_ATTR_IS_SYSTEM_GENERATED, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.data_type); + err = dbt_put_internal (obt_p, SP_ATTR_DATA_TYPE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.mode); + err = dbt_put_internal (obt_p, SP_ATTR_MODE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.is_optional); + err = dbt_put_internal (obt_p, SP_ATTR_IS_OPTIONAL, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + err = dbt_put_internal (obt_p, SP_ATTR_DEFAULT_VALUE, &info.default_value); + if (err != NO_ERROR) + { + goto error; + } + + if (!info.comment.empty ()) + { + db_make_string (&value, info.comment.data ()); + } + err = dbt_put_internal (obt_p, SP_ATTR_ARG_COMMENT, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + object_p = dbt_finish_object (obt_p); + if (!object_p) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + obt_p = NULL; + + err = locator_flush_instance (object_p); + if (err != NO_ERROR) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + obj_delete (object_p); + goto error; + } + + *mop_p = object_p; + + AU_ENABLE (save); + return NO_ERROR; + +error: + if (obt_p) + { + dbt_abort_object (obt_p); + } + + AU_ENABLE (save); + return err; +} + +int +sp_add_stored_procedure_code (SP_CODE_INFO &info) +{ + DB_OBJECT *classobj_p, *object_p; + DB_OTMPL *obt_p = NULL; + DB_VALUE value; + int save; + int err; + + AU_DISABLE (save); + + classobj_p = db_find_class (SP_CODE_CLASS_NAME); + if (classobj_p == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + obt_p = dbt_create_object_internal (classobj_p); + if (obt_p == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + db_make_string (&value, info.created_time.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_TIMESTAMP, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_object (&value, info.owner); + err = dbt_put_internal (obt_p, SP_ATTR_OWNER, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_string (&value, info.name.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_CLS_NAME, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_int (&value, info.stype); + err = dbt_put_internal (obt_p, SP_ATTR_SOURCE_TYPE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_varchar (&value, DB_DEFAULT_PRECISION, info.scode.data (), info.scode.length (), LANG_SYS_CODESET, + LANG_SYS_COLLATION); + err = dbt_put_internal (obt_p, SP_ATTR_SOURCE_CODE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + + db_make_int (&value, info.otype); + err = dbt_put_internal (obt_p, SP_ATTR_OBJECT_TYPE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + db_make_varchar (&value, DB_DEFAULT_PRECISION, info.ocode.data (), info.ocode.length (), LANG_SYS_CODESET, + LANG_SYS_COLLATION); + err = dbt_put_internal (obt_p, SP_ATTR_OBJECT_CODE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + object_p = dbt_finish_object (obt_p); + if (!object_p) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + obt_p = NULL; + + err = locator_flush_instance (object_p); + if (err != NO_ERROR) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + obj_delete (object_p); + goto error; + } + + AU_ENABLE (save); + return NO_ERROR; + +error: + if (obt_p) + { + dbt_abort_object (obt_p); + } + + AU_ENABLE (save); + return err; +} + +int +sp_edit_stored_procedure_code (MOP code_mop, SP_CODE_INFO &info) +{ + DB_OBJECT *object_p; + DB_OTMPL *obt_p = NULL; + DB_VALUE value; + int save; + int err; + + AU_DISABLE (save); + + obt_p = dbt_edit_object (code_mop); + if (obt_p == NULL) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + + db_make_string (&value, info.name.data ()); + err = dbt_put_internal (obt_p, SP_ATTR_CLS_NAME, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + if (info.owner != NULL) + { + db_make_object (&value, info.owner); + err = dbt_put_internal (obt_p, SP_ATTR_OWNER, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + } + + db_make_varchar (&value, DB_DEFAULT_PRECISION, info.ocode.data (), info.ocode.length (), LANG_SYS_CODESET, + LANG_SYS_COLLATION); + err = dbt_put_internal (obt_p, SP_ATTR_OBJECT_CODE, &value); + pr_clear_value (&value); + if (err != NO_ERROR) + { + goto error; + } + + object_p = dbt_finish_object (obt_p); + if (!object_p) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + goto error; + } + obt_p = NULL; + + err = locator_flush_instance (object_p); + if (err != NO_ERROR) + { + assert (er_errid () != NO_ERROR); + err = er_errid (); + obj_delete (object_p); + goto error; + } + + AU_ENABLE (save); + return NO_ERROR; + +error: + if (obt_p) + { + dbt_abort_object (obt_p); + } + + AU_ENABLE (save); + return err; +} + +void sp_normalize_name (std::string &s) +{ + s.resize (SM_MAX_IDENTIFIER_LENGTH); + sm_downcase_name (s.data (), s.data (), SM_MAX_IDENTIFIER_LENGTH); +} + +void +sp_split_target_signature (const std::string &s, std::string &target_cls, std::string &target_mth) +{ + auto pos = s.find_last_of ('('); + if (pos == std::string::npos) + { + // handle the case where '(' is not found, if necessary + target_cls.clear(); + target_mth.clear(); + return; + } + + pos = s.substr (0, pos).find_last_of ('.'); + if (pos == std::string::npos) + { + // handle the case where '.' is not found, if necessary + target_cls.clear(); + target_mth.clear(); + return; + } + + target_cls = s.substr (0, pos); + target_mth = s.substr (pos + 1); // +1 to skip the '.' +} + +std::string +sp_get_entry_name (int index) +{ + return sp_entry_names[index]; +} + +std::string +sp_args_get_entry_name (int index) +{ + return sp_args_entry_names[index]; +} \ No newline at end of file diff --git a/src/sp/sp_catalog.hpp b/src/sp/sp_catalog.hpp new file mode 100644 index 00000000000..54585d1ef5b --- /dev/null +++ b/src/sp/sp_catalog.hpp @@ -0,0 +1,203 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +/* + * sp_catalog.hpp - Define stored procedure related system catalog's row sturcture and initializer + * + * Note: _db_stored_proceudre, _db_stored_procedure_args + */ + +#ifndef _SP_DEFINITION_HPP_ +#define _SP_DEFINITION_HPP_ + +#include +#include + +#include "jsp_cl.h" +#include "dbi.h" + +#define SAVEPOINT_ADD_STORED_PROC "ADDSTOREDPROC" +#define SAVEPOINT_CREATE_STORED_PROC "CREATESTOREDPROC" + +enum sp_source_code_type +{ + SPSC_PLCSQL, + SPSC_JAVA +}; + +enum sp_object_code_type +{ + SPOC_JAVA_CLASS, + SPOC_JAVA_JAR +}; + +enum sp_entry_index +{ + SP_ATTR_INDEX_UNIQUE_NAME, + SP_ATTR_INDEX_NAME, + SP_ATTR_INDEX_SP_TYPE, + SP_ATTR_INDEX_RETURN_TYPE, + SP_ATTR_INDEX_ARG_COUNT, + SP_ATTR_INDEX_ARGS, + SP_ATTR_INDEX_LANG, + SP_ATTR_INDEX_PKG, + SP_ATTR_INDEX_IS_SYSTEM_GENERATED, + SP_ATTR_INDEX_TARGET_CLASS, + SP_ATTR_INDEX_TARGET_METHOD, + SP_ATTR_INDEX_DIRECTIVE, + SP_ATTR_INDEX_OWNER, + SP_ATTR_INDEX_COMMENT, + SP_ATTR_INDEX_LAST +}; + + +enum sp_args_entry_index +{ + SP_ARGS_ATTR_INDEX_SP_OF, + SP_ARGS_ATTR_INDEX_PKG, + SP_ARGS_ATTR_INDEX_OF, + SP_ARGS_ATTR_INDEX_IS_SYSTEM_GENERATED, + SP_ARGS_ATTR_INDEX_ARG_NAME, + SP_ARGS_ATTR_INDEX_DATA_TYPE, + SP_ARGS_ATTR_INDEX_MODE, + SP_ARGS_ATTR_INDEX_DEFAULT_VALUE, + SP_ARGS_ATTR_INDEX_IS_OPTIONAL, + SP_ARGS_ATTR_INDEX_COMMENT, + SP_ARGS_ATTR_INDEX_LAST +}; + +// entry +// TODO: move to proper place to commonly use for any catalog +struct sp_entry +{ + OID oid; /* catalog row's oid */ + std::vector vals; + + sp_entry (int size); + ~sp_entry (); +}; + +// *INDENT-OFF* +struct sp_arg_info +{ + std::string sp_name; + std::string pkg_name; + int index_of; + bool is_system_generated; + std::string arg_name; + DB_TYPE data_type; + SP_MODE_ENUM mode; + DB_VALUE default_value; + bool is_optional; + std::string comment; + + sp_arg_info (const std::string& s_name, const std::string& p_name) + : sp_name {s_name} + , pkg_name {p_name} + , index_of {SP_TYPE_ENUM::SP_TYPE_PROCEDURE} + , is_system_generated {false} + , arg_name {} + , data_type {DB_TYPE::DB_TYPE_NULL} + , mode {SP_MODE_ENUM::SP_MODE_IN} + , default_value {} + , is_optional {false} + , comment {} + {} + + sp_arg_info () + : sp_arg_info ("", "") + {} +}; +typedef sp_arg_info SP_ARG_INFO; + +enum sp_directive : int +{ + SP_DIRECTIVE_RIGHTS_OWNER = 0x00, + SP_DIRECTIVE_RIGHTS_CALLER = (0x01 << 0), +}; +typedef sp_directive SP_DIRECTIVE_ENUM; + +struct sp_code_info +{ + std::string name; + std::string created_time; + MOP owner; + int is_static; + int is_system_generated; + int stype; + std::string scode; + int otype; + std::string ocode; +}; +typedef sp_code_info SP_CODE_INFO; + +struct sp_info +{ + std::string unique_name; + std::string sp_name; + std::string pkg_name; + SP_TYPE_ENUM sp_type; + DB_TYPE return_type; + bool is_system_generated; + std::vector args; + SP_LANG_ENUM lang; + std::string target_class; + std::string target_method; + SP_DIRECTIVE_ENUM directive; + MOP owner; + std::string comment; + + sp_info () + : unique_name {} + , sp_name {} + , pkg_name {} + , sp_type {SP_TYPE_ENUM::SP_TYPE_PROCEDURE} + , return_type {DB_TYPE::DB_TYPE_NULL} + , is_system_generated {false} + , args {} + , lang {SP_LANG_ENUM::SP_LANG_PLCSQL} + , target_class {} + , target_method {} + , directive {SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_OWNER} + , owner {nullptr} + , comment {} + {} +}; +typedef sp_info SP_INFO; +// *INDENT-ON* + +int sp_builtin_install (); + +// insert into system catalogs +int sp_add_stored_procedure (SP_INFO &info); +int sp_add_stored_procedure_argument (MOP *mop_p, SP_ARG_INFO &info); +int sp_add_stored_procedure_code (SP_CODE_INFO &info); + +// update into system catalogs +int sp_edit_stored_procedure_code (MOP code_mop, SP_CODE_INFO &info); + +// getter +std::string sp_get_entry_name (int index); +std::string sp_args_get_entry_name (int index); + +// misc +void sp_normalize_name (std::string &s); +void sp_split_target_signature (const std::string &s, std::string &target_cls, std::string &target_mth); + +#endif // _SP_DEFINITION_HPP_ diff --git a/src/sp/sp_code.cpp b/src/sp/sp_code.cpp new file mode 100644 index 00000000000..28de0a72485 --- /dev/null +++ b/src/sp/sp_code.cpp @@ -0,0 +1,264 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// +// sp_code.cpp +// + +#include "sp_code.hpp" + +#include +#include + +#include "dbtype.h" +#include "heap_file.h" +#include "object_representation_sr.h" +#include "sp_constants.hpp" + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" + +ATTR_ID spcode_Attrs_id[SPC_ATTR_MAX_INDEX]; +int spcode_Num_attrs = -1; + +static int sp_load_sp_code_attribute_info (THREAD_ENTRY *thread_p); +static void sp_code_attr_init (); +static int sp_get_attrid (THREAD_ENTRY *thread_p, int attr_index, ATTR_ID &attrid); +static int sp_get_attr_idx (const std::string &attr_name); + +using sp_code_attr_map_type = std::unordered_map ; +static sp_code_attr_map_type attr_idx_map; + +static void +sp_code_attr_init () +{ + attr_idx_map [SP_ATTR_CLS_NAME] = SPC_ATTR_NAME_INDEX; + attr_idx_map [SP_ATTR_TIMESTAMP] = SPC_ATTR_CREATED_TIME; + attr_idx_map [SP_ATTR_OWNER] = SPC_ATTR_OWNER_INDEX; + attr_idx_map [SP_ATTR_IS_STATIC] = SPC_ATTR_IS_STATIC_INDEX; + attr_idx_map [SP_ATTR_IS_SYSTEM_GENERATED] = SPC_ATTR_IS_SYSTEM_GENERATED_INDEX; + attr_idx_map [SP_ATTR_SOURCE_TYPE] = SPC_ATTR_STYPE_INDEX; + attr_idx_map [SP_ATTR_SOURCE_CODE] = SPC_ATTR_SCODE_INDEX; + attr_idx_map [SP_ATTR_OBJECT_TYPE] = SPC_ATTR_OTYPE_INDEX; + attr_idx_map [SP_ATTR_OBJECT_CODE] = SPC_ATTR_OCODE_INDEX; +} + +static int +sp_get_attr_idx (const std::string &attr_name) +{ + if (attr_idx_map.size () == 0) + { + sp_code_attr_init (); + } + + auto idx_it = attr_idx_map.find (attr_name); + if (idx_it == attr_idx_map.end ()) + { + return -1; + } + else + { + return idx_it->second; + } +} + +int +sp_get_code_attr (THREAD_ENTRY *thread_p, const std::string &attr_name, const OID *sp_oidp, DB_VALUE *result) +{ + int ret = NO_ERROR; + HEAP_SCANCACHE scan_cache; + SCAN_CODE scan; + RECDES recdesc = RECDES_INITIALIZER; + HEAP_CACHE_ATTRINFO attr_info, *attr_info_p = NULL; + ATTR_ID attrid; + DB_VALUE *cur_val; + OID *sp_class_oid = oid_Sp_code_class_oid; + int idx = -1; + + heap_scancache_quick_start_with_class_oid (thread_p, &scan_cache, sp_class_oid); + /* get record into record desc */ + scan = heap_get_visible_version (thread_p, sp_oidp, sp_class_oid, &recdesc, &scan_cache, PEEK, NULL_CHN); + if (scan != S_SUCCESS) + { + if (er_errid () == ER_PB_BAD_PAGEID) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HEAP_UNKNOWN_OBJECT, 3, sp_oidp->volid, sp_oidp->pageid, + sp_oidp->slotid); + } + else + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_QPROC_CANNOT_FETCH_SERIAL, 0); + } + goto exit_on_error; + } + + /* retrieve attribute */ + idx = sp_get_attr_idx (attr_name); + if (idx == -1) + { + goto exit_on_error; + } + + if (sp_get_attrid (thread_p, idx, attrid) != NO_ERROR) + { + goto exit_on_error; + } + + assert (attrid != -1); + + ret = heap_attrinfo_start (thread_p, sp_class_oid, 1, &attrid, &attr_info); + if (ret != NO_ERROR) + { + goto exit_on_error; + } + + attr_info_p = &attr_info; + + ret = heap_attrinfo_read_dbvalues (thread_p, sp_oidp, &recdesc, attr_info_p); + if (ret != NO_ERROR) + { + goto exit_on_error; + } + + cur_val = heap_attrinfo_access (attrid, attr_info_p); + + db_value_clone (cur_val, result); + + heap_attrinfo_end (thread_p, attr_info_p); + + heap_scancache_end (thread_p, &scan_cache); + + return NO_ERROR; + +exit_on_error: + + if (attr_info_p != NULL) + { + heap_attrinfo_end (thread_p, attr_info_p); + } + + heap_scancache_end (thread_p, &scan_cache); + + ret = (ret == NO_ERROR && (ret = er_errid ()) == NO_ERROR) ? ER_FAILED : ret; + return ret; +} + +static int +sp_get_attrid (THREAD_ENTRY *thread_p, int attr_index, ATTR_ID &attrid) +{ + attrid = -1; // NOT FOUND + + if (spcode_Num_attrs < 0) + { + int error = sp_load_sp_code_attribute_info (thread_p); + if (error != NO_ERROR) + { + ASSERT_ERROR (); + return error; + } + } + + if (attr_index >= 0 && attr_index <= spcode_Num_attrs) + { + attrid = spcode_Attrs_id[attr_index]; + } + return NO_ERROR; +} + +static int +sp_load_sp_code_attribute_info (THREAD_ENTRY *thread_p) +{ + HEAP_SCANCACHE scan; + RECDES class_record; + HEAP_CACHE_ATTRINFO attr_info; + int i, error = NO_ERROR; + char *attr_name_p, *string = NULL; + int alloced_string = 0; + int attr_idx = -1; + + if (spcode_Num_attrs != -1) + { + // already retrived + return error; + } + + OID *sp_code_oid_class = oid_Sp_code_class_oid; + spcode_Num_attrs = -1; + + if (heap_scancache_quick_start_with_class_oid (thread_p, &scan, sp_code_oid_class) != NO_ERROR) + { + return ER_FAILED; + } + if (heap_get_class_record (thread_p, sp_code_oid_class, &class_record, &scan, PEEK) != S_SUCCESS) + { + heap_scancache_end (thread_p, &scan); + return ER_FAILED; + } + + error = heap_attrinfo_start (thread_p, sp_code_oid_class, -1, NULL, &attr_info); + if (error != NO_ERROR) + { + (void) heap_scancache_end (thread_p, &scan); + return error; + } + + for (i = 0; i < attr_info.num_values; i++) + { + string = NULL; + alloced_string = 0; + + error = or_get_attrname (&class_record, i, &string, &alloced_string); + if (error != NO_ERROR) + { + ASSERT_ERROR (); + goto exit_on_error; + } + + attr_name_p = string; + if (attr_name_p == NULL) + { + error = ER_FAILED; + goto exit_on_error; + } + + attr_idx = sp_get_attr_idx (attr_name_p); + if (attr_idx != -1) + { + spcode_Attrs_id [attr_idx] = i; + } + + if (string != NULL && alloced_string) + { + db_private_free_and_init (NULL, string); + } + + } + spcode_Num_attrs = attr_info.num_values; + + heap_attrinfo_end (thread_p, &attr_info); + error = heap_scancache_end (thread_p, &scan); + + return error; + +exit_on_error: + + heap_attrinfo_end (thread_p, &attr_info); + (void) heap_scancache_end (thread_p, &scan); + + return error; +} diff --git a/src/sp/sp_code.hpp b/src/sp/sp_code.hpp new file mode 100644 index 00000000000..d5947834ca7 --- /dev/null +++ b/src/sp/sp_code.hpp @@ -0,0 +1,55 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// +// sp_code.hpp +// + +#ifndef _SP_CODE_HPP_ +#define _SP_CODE_HPP_ + +#ident "$Id$" + +#include + +#include "dbtype_def.h" +#include "query_list.h" /* QUERY_ID, QFILE_LIST_ID */ +#include "query_manager.h" + +// thread_entry.hpp +namespace cubthread +{ + class entry; +} + +enum SP_CODE_ATTRIBUTES +{ + SPC_ATTR_NAME_INDEX, + SPC_ATTR_CREATED_TIME, + SPC_ATTR_OWNER_INDEX, + SPC_ATTR_IS_STATIC_INDEX, + SPC_ATTR_IS_SYSTEM_GENERATED_INDEX, + SPC_ATTR_STYPE_INDEX, + SPC_ATTR_SCODE_INDEX, + SPC_ATTR_OTYPE_INDEX, + SPC_ATTR_OCODE_INDEX, + SPC_ATTR_MAX_INDEX +}; + +int sp_get_code_attr (THREAD_ENTRY *thread_p, const std::string &attr_name, const OID *sp_oidp, DB_VALUE *result); +#endif /* _SP_CODE_HPP_ */ diff --git a/src/sp/sp_constants.hpp b/src/sp/sp_constants.hpp new file mode 100644 index 00000000000..2503969d8eb --- /dev/null +++ b/src/sp/sp_constants.hpp @@ -0,0 +1,179 @@ +/* + * + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SP_CONSTASNTS_HPP_ +#define _SP_CONSTASNTS_HPP_ + +#define SP_CLASS_NAME "_db_stored_procedure" +#define SP_ARG_CLASS_NAME "_db_stored_procedure_args" +#define SP_CODE_CLASS_NAME "_db_stored_procedure_code" + +#define SP_ATTR_UNIQUE_NAME "unique_name" +#define SP_ATTR_NAME "sp_name" +#define SP_ATTR_SP_TYPE "sp_type" +#define SP_ATTR_RETURN_TYPE "return_type" +#define SP_ATTR_ARGS "args" +#define SP_ATTR_ARG_COUNT "arg_count" +#define SP_ATTR_LANG "lang" +#define SP_ATTR_PKG "pkg_name" +#define SP_ATTR_IS_SYSTEM_GENERATED "is_system_generated" +#define SP_ATTR_TARGET_CLASS "target_class" +#define SP_ATTR_TARGET_METHOD "target_method" +#define SP_ATTR_DIRECTIVE "directive" +#define SP_ATTR_OWNER "owner" +#define SP_ATTR_COMMENT "comment" + +#define SP_ATTR_SP_OF "sp_of" +#define SP_ATTR_ARG_NAME "arg_name" +#define SP_ATTR_INDEX_OF_NAME "index_of" +#define SP_ATTR_DATA_TYPE "data_type" +#define SP_ATTR_MODE "mode" +#define SP_ATTR_DEFAULT_VALUE "default_value" +#define SP_ATTR_IS_OPTIONAL "is_optional" +#define SP_ATTR_ARG_COMMENT "comment" + +#define SP_ATTR_CLS_NAME "name" +#define SP_ATTR_TIMESTAMP "created_time" +#define SP_ATTR_IS_STATIC "is_static" +#define SP_ATTR_SOURCE_TYPE "stype" +#define SP_ATTR_SOURCE_CODE "scode" +#define SP_ATTR_OBJECT_TYPE "otype" +#define SP_ATTR_OBJECT_CODE "ocode" + +#define SP_MAX_DEFAULT_VALUE_LEN 255 + +typedef enum +{ + SP_TYPE_PROCEDURE = 1, + SP_TYPE_FUNCTION +} SP_TYPE_ENUM; + +typedef enum +{ + SP_MODE_IN = 1, + SP_MODE_OUT, + SP_MODE_INOUT +} SP_MODE_ENUM; + +typedef enum +{ + SP_LANG_PLCSQL = 0, + SP_LANG_JAVA = 1 +} SP_LANG_ENUM; + +// refactor following + +#define METHOD_MAX_RECURSION_DEPTH 15 + +typedef enum +{ + METHOD_SUCCESS = 1, + METHOD_EOF, + METHOD_ERROR +} METHOD_CALL_STATUS; + +enum METHOD_TYPE +{ + METHOD_TYPE_NONE = 0, + METHOD_TYPE_INSTANCE_METHOD, + METHOD_TYPE_CLASS_METHOD, + METHOD_TYPE_JAVA_SP, + METHOD_TYPE_PLCSQL +}; + +enum METHOD_AUTH +{ + METHOD_AUTH_OWNER = 0, + METHOD_AUTH_INVOKER = 1 +}; + +enum METHOD_REQUEST +{ + METHOD_REQUEST_ARG_PREPARE = 0x40, + METHOD_REQUEST_INVOKE = 0x01, + METHOD_REQUEST_CALLBACK = 0x08, + METHOD_REQUEST_END = 0x20, + + METHOD_REQUEST_COMPILE = 0x80, + METHOD_REQUEST_SQL_SEMANTICS = 0xA0, + METHOD_REQUEST_GLOBAL_SEMANTICS = 0xA1 +}; + +enum METHOD_RESPONSE +{ + METHOD_RESPONSE_SUCCESS, + METHOD_RESPONSE_ERROR +}; + +enum METHOD_CALLBACK_RESPONSE +{ + METHOD_CALLBACK_END_TRANSACTION = 1, + METHOD_CALLBACK_QUERY_PREPARE = 2, + METHOD_CALLBACK_QUERY_EXECUTE = 3, + METHOD_CALLBACK_GET_DB_PARAMETER = 4, + + METHOD_CALLBACK_CURSOR = 7, + METHOD_CALLBACK_FETCH = 8, + METHOD_CALLBACK_GET_SCHEMA_INFO = 9, + + METHOD_CALLBACK_OID_GET = 10, + METHOD_CALLBACK_OID_PUT = 11, + METHOD_CALLBACK_OID_CMD = 17, + METHOD_CALLBACK_COLLECTION = 18, + + // METHOD_CALLBACK_GET_DB_VERSION = 15, + + METHOD_CALLBACK_NEXT_RESULT = 19, + + METHOD_CALLBACK_EXECUTE_BATCH = 20, + METHOD_CALLBACK_EXECUTE_ARRAY = 21, + + METHOD_CALLBACK_CURSOR_UPDATE = 22, + + METHOD_CALLBACK_MAKE_OUT_RS = 33, + METHOD_CALLBACK_GET_GENERATED_KEYS = 34, + + METHOD_CALLBACK_LOB_NEW = 35, + METHOD_CALLBACK_LOB_WRITE = 36, + METHOD_CALLBACK_LOB_READ = 37, + + METHOD_CALLBACK_CURSOR_CLOSE = 42, + + // COMPILE + METHOD_CALLBACK_GET_SQL_SEMANTICS = 100, + METHOD_CALLBACK_GET_GLOBAL_SEMANTICS = 101, + + // AUTH + METHOD_CALLBACK_CHANGE_RIGHTS = 200, + + // CLASS ACCESS + METHOD_CALLBACK_GET_CODE_ATTR = 201 +}; + +enum METHOD_ARG_MODE +{ + METHOD_ARG_MODE_IN = 1, + METHOD_ARG_MODE_OUT, + METHOD_ARG_MODE_INOUT +}; + +#define METHOD_GROUP_ID uint64_t +#define METHOD_REQ_ID int + + +#endif // _SP_CONSTASNTS_HPP_ \ No newline at end of file diff --git a/src/storage/oid.c b/src/storage/oid.c index 883a0c1ae58..fd43aa2c09d 100644 --- a/src/storage/oid.c +++ b/src/storage/oid.c @@ -57,6 +57,7 @@ static OID oid_Datatype_class = { 0, 0, 0 }; static OID oid_Classauth_class = { 0, 0, 0 }; static OID oid_Stored_proc_class = { 0, 0, 0 }; static OID oid_Stored_proc_args_class = { 0, 0, 0 }; +static OID oid_Stored_proc_code_class = { 0, 0, 0 }; static OID oid_Charset_class = { 0, 0, 0 }; static OID oid_Trigger_class = { 0, 0, 0 }; static OID oid_User_class = { 0, 0, 0 }; @@ -80,7 +81,7 @@ OID *oid_Root_class_oid = &oid_Root_class; OID *oid_Serial_class_oid = &oid_Serial_class; OID *oid_Partition_class_oid = &oid_Partition_class; OID *oid_User_class_oid = &oid_User_class; - +OID *oid_Sp_code_class_oid = &oid_Stored_proc_code_class; OID_CACHE_ENTRY oid_Cache[OID_CACHE_SIZE] = { {&oid_Root_class, NULL}, /* Root class is not identifiable by a name */ @@ -110,7 +111,8 @@ OID_CACHE_ENTRY oid_Cache[OID_CACHE_SIZE] = { {&oid_Authorizations_class, CT_AUTHORIZATIONS_NAME}, {&oid_DB_root_class, CT_ROOT_NAME}, {&oid_DBServer_class, CT_DB_SERVER_NAME}, - {&oid_Synonym_class, CT_SYNONYM_NAME} + {&oid_Synonym_class, CT_SYNONYM_NAME}, + {&oid_Stored_proc_code_class, CT_STORED_PROC_CODE_NAME}, }; /* diff --git a/src/storage/oid.h b/src/storage/oid.h index 84e79e3578a..5d4acb935c9 100644 --- a/src/storage/oid.h +++ b/src/storage/oid.h @@ -201,6 +201,7 @@ enum OID_CACHE_DB_ROOT_CLASS_ID, OID_CACHE_DB_SERVER_CLASS_ID, OID_CACHE_SYNONYM_CLASS_ID, + OID_CACHE_STORED_PROC_CODE_CLASS_ID, OID_CACHE_SIZE }; @@ -209,6 +210,8 @@ extern const OID oid_Null_oid; extern OID *oid_Root_class_oid; extern OID *oid_Serial_class_oid; extern OID *oid_User_class_oid; +extern OID *oid_Sp_code_class_oid; + extern PAGEID oid_Next_tempid; extern void oid_set_root (const OID * oid); diff --git a/src/transaction/boot_cl.c b/src/transaction/boot_cl.c index 70348e20803..b7efad93306 100644 --- a/src/transaction/boot_cl.c +++ b/src/transaction/boot_cl.c @@ -88,6 +88,7 @@ #include "connection_globals.h" #include "host_lookup.h" #include "schema_system_catalog.hpp" +#include "sp_catalog.hpp" #include "authenticate_context.hpp" @@ -566,6 +567,11 @@ boot_initialize_client (BOOT_CLIENT_CREDENTIAL * client_credential, BOOT_DB_PATH sm_mark_system_classes (); error_code = tran_commit (false); } + + if (error_code == NO_ERROR) + { + error_code = sp_builtin_install (); + } } } } diff --git a/src/transaction/boot_sr.c b/src/transaction/boot_sr.c index 54d3f1223d9..99031330b81 100644 --- a/src/transaction/boot_sr.c +++ b/src/transaction/boot_sr.c @@ -67,7 +67,7 @@ #include "serial.h" #include "server_interface.h" #include "jansson.h" -#include "jsp_sr.h" +#include "pl_sr.h" #include "xserver_interface.h" #include "session.h" #include "event_log.h" @@ -87,6 +87,7 @@ #if defined(SERVER_MODE) #include "connection_sr.h" #include "server_support.h" +#include "pl_sr.h" #endif /* SERVER_MODE */ #if defined(WINDOWS) @@ -2072,8 +2073,8 @@ boot_restart_server (THREAD_ENTRY * thread_p, bool print_restart, const char *db char timezone_checksum[32 + 1]; const TZ_DATA *tzd; char *mk_path; - int jsp_port; - bool jsp; + int pl_port; + bool pl; /* language data is loaded in context of server */ if (lang_init () != NO_ERROR) @@ -2299,20 +2300,7 @@ boot_restart_server (THREAD_ENTRY * thread_p, bool print_restart, const char *db tsc_init (); #endif /* !SERVER_MODE */ - #if defined (SA_MODE) - // Initialize java stored procedure server for standalone mode - jsp = prm_get_bool_value (PRM_ID_JAVA_STORED_PROCEDURE); - if (jsp && !jsp_jvm_is_loaded ()) - { - jsp_port = prm_get_integer_value (PRM_ID_JAVA_STORED_PROCEDURE_PORT); - error_code = jsp_start_server (db_name, db->pathname, jsp_port); - if (error_code != NO_ERROR) - { - goto error; - } - } - /* *INDENT-OFF* */ // thread_manager was not initialized assert (thread_p == NULL); @@ -2789,6 +2777,8 @@ boot_restart_server (THREAD_ENTRY * thread_p, bool print_restart, const char *db json_set_alloc_funcs (malloc, free); #endif + pl_server_init (db_name); + return NO_ERROR; error: @@ -2817,10 +2807,13 @@ boot_restart_server (THREAD_ENTRY * thread_p, bool print_restart, const char *db session_states_finalize (thread_p); logtb_finalize_global_unique_stats_table (thread_p); + vacuum_stop_workers (thread_p); vacuum_stop_master (thread_p); #if defined(SERVER_MODE) + pl_server_destroy (); + cdc_daemons_destroy (); BO_DISABLE_FLUSH_DAEMONS (); @@ -3139,6 +3132,7 @@ xboot_shutdown_server (REFPTR (THREAD_ENTRY, thread_p), ER_FINAL_CODE is_er_fina #if defined(SERVER_MODE) pgbuf_daemons_destroy (); cdc_daemons_destroy (); + pl_server_destroy (); #endif #if defined (SA_MODE) diff --git a/src/transaction/log_tran_table.c b/src/transaction/log_tran_table.c index c030d9de111..ec0beea41d5 100644 --- a/src/transaction/log_tran_table.c +++ b/src/transaction/log_tran_table.c @@ -77,7 +77,8 @@ #include "thread_manager.hpp" #include "xasl.h" #include "xasl_cache.h" -#include "method_runtime_context.hpp" +#include "pl_session.hpp" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" @@ -2761,6 +2762,12 @@ logtb_set_tran_index_interrupt (THREAD_ENTRY * thread_p, int tran_index, bool se pgbuf_force_to_check_for_interrupts (); er_set (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_INTERRUPTING, 1, tran_index); perfmon_inc_stat (thread_p, PSTAT_TRAN_NUM_INTERRUPTS); + + cubpl::session * session = cubpl::get_session (); + if (session) + { + session->set_interrupt (ER_INTERRUPTED); + } } return true; @@ -2834,10 +2841,10 @@ logtb_is_interrupted_tdes (THREAD_ENTRY * thread_p, LOG_TDES * tdes, bool clear, #endif } - cubmethod::runtime_context * rctx = cubmethod::get_rctx (thread_p); - if (rctx) + cubpl::session * session = cubpl::get_session (); + if (session) { - rctx->set_interrupt (ER_INTERRUPTED); + session->set_interrupt (ER_INTERRUPTED); } } else if (interrupt == false && tdes->query_timeout > 0) @@ -6073,7 +6080,21 @@ log_tdes::lock_topop () { if (LOG_ISRESTARTED () && is_active_worker_transaction ()) { - int r = rmutex_lock (NULL, &rmutex_topop); + cubthread::entry *thread_p = NULL; +// TODO [PL/CSQL]: It will be fixed at CBRD-25641. +// The following code inside of #if block is a workaround for the issue. +#if 1 + if (rmutex_topop.owner != thread_id_t ()) + { + cubpl::session *session = cubpl::get_session(); + if (session + && session->is_thread_involved (rmutex_topop.owner)) + { + thread_p = thread_get_manager ()->find_by_tid (rmutex_topop.owner); + } + } +#endif + int r = rmutex_lock (thread_p, &rmutex_topop); assert (r == NO_ERROR); } } @@ -6083,7 +6104,21 @@ log_tdes::unlock_topop () { if (LOG_ISRESTARTED () && is_active_worker_transaction ()) { - int r = rmutex_unlock (NULL, &rmutex_topop); + cubthread::entry *thread_p = NULL; +// TODO [PL/CSQL]: It will be fixed at CBRD-25641. +// The following code inside of #if block is a workaround for the issue. +#if 1 + if (rmutex_topop.owner != thread_id_t ()) + { + cubpl::session *session = cubpl::get_session(); + if (session + && session->is_thread_involved (rmutex_topop.owner)) + { + thread_p = thread_get_manager ()->find_by_tid (rmutex_topop.owner); + } + } +#endif + int r = rmutex_unlock (thread_p, &rmutex_topop); assert (r == NO_ERROR); } } diff --git a/src/transaction/transaction_cl.c b/src/transaction/transaction_cl.c index 94592634fc9..50019d645ce 100644 --- a/src/transaction/transaction_cl.c +++ b/src/transaction/transaction_cl.c @@ -292,7 +292,7 @@ tran_commit (bool retain_lock) } assert (!tran_was_latest_query_aborted ()); - if (tran_was_latest_query_ended ()) + if (tran_was_latest_query_ended () || tran_is_in_libcas ()) { /* Query ended with latest executed query. No need to notify server. */ query_end_notify_server = false; diff --git a/src/win_tools/ctrlservice/ctrlservice.cpp b/src/win_tools/ctrlservice/ctrlservice.cpp index 0eb5209446b..c9be9eb72f1 100644 --- a/src/win_tools/ctrlservice/ctrlservice.cpp +++ b/src/win_tools/ctrlservice/ctrlservice.cpp @@ -62,8 +62,8 @@ #define SERVICE_CONTROL_SERVER_STOP 181 #define SERVICE_CONTROL_SERVICE_START 190 #define SERVICE_CONTROL_SERVICE_STOP 191 -#define SERVICE_CONTROL_JAVASP_START 210 -#define SERVICE_CONTROL_JAVASP_STOP 211 +#define SERVICE_CONTROL_PL_START 210 +#define SERVICE_CONTROL_PL_STOP 211 void WriteLog (char *p_logfile, char *p_format, ...); void GetCurDateTime (char *p_buf, char *p_form); @@ -335,11 +335,11 @@ _tmain (int argc, char *argv[]) } else if (_stricmp (argv[1], CUBRID_UTIL_JAVASP) == 0 && _stricmp (argv[2], CUBRID_COMMAND_START) == 0) { - service_control_code = SERVICE_CONTROL_JAVASP_START; + service_control_code = SERVICE_CONTROL_PL_START; } else if (_stricmp (argv[1], CUBRID_UTIL_JAVASP) == 0 && _stricmp (argv[2], CUBRID_COMMAND_STOP) == 0) { - service_control_code = SERVICE_CONTROL_JAVASP_STOP; + service_control_code = SERVICE_CONTROL_PL_STOP; } else { diff --git a/src/win_tools/cubridservice/cubridservice.cpp b/src/win_tools/cubridservice/cubridservice.cpp index 2530e495e3d..de14137b512 100644 --- a/src/win_tools/cubridservice/cubridservice.cpp +++ b/src/win_tools/cubridservice/cubridservice.cpp @@ -67,8 +67,8 @@ BOOL g_isRunning = false; #define SERVICE_CONTROL_SERVER_STOP 181 #define SERVICE_CONTROL_SERVICE_START 190 #define SERVICE_CONTROL_SERVICE_STOP 191 -#define SERVICE_CONTROL_JAVASP_START 210 -#define SERVICE_CONTROL_JAVASP_STOP 211 +#define SERVICE_CONTROL_PL_START 210 +#define SERVICE_CONTROL_PL_STOP 211 #define CUBRID_UTIL_CUBRID "cubrid.exe" #define CUBRID_UTIL_SERVICE "service" @@ -195,8 +195,8 @@ vHandler (DWORD opcode) if (opcode == SERVICE_CONTROL_SERVER_START || opcode == SERVICE_CONTROL_SERVER_STOP || - opcode == SERVICE_CONTROL_JAVASP_START || - opcode == SERVICE_CONTROL_JAVASP_STOP || + opcode == SERVICE_CONTROL_PL_START || + opcode == SERVICE_CONTROL_PL_STOP || opcode == SERVICE_CONTROL_BROKER_ON || opcode == SERVICE_CONTROL_BROKER_OFF || opcode == SERVICE_CONTROL_GATEWAY_ON || opcode == SERVICE_CONTROL_GATEWAY_OFF) @@ -359,7 +359,7 @@ vHandler (DWORD opcode) args[5] = NULL; } break; - case SERVICE_CONTROL_JAVASP_START: + case SERVICE_CONTROL_PL_START: { args[1] = CUBRID_UTIL_JAVASP; args[2] = CUBRID_COMMAND_START; @@ -367,7 +367,7 @@ vHandler (DWORD opcode) args[5] = NULL; } break; - case SERVICE_CONTROL_JAVASP_STOP: + case SERVICE_CONTROL_PL_STOP: { args[1] = CUBRID_UTIL_JAVASP; args[2] = CUBRID_COMMAND_STOP; @@ -384,8 +384,8 @@ vHandler (DWORD opcode) if (opcode == SERVICE_CONTROL_SERVER_START || opcode == SERVICE_CONTROL_SERVER_STOP || - opcode == SERVICE_CONTROL_JAVASP_START || - opcode == SERVICE_CONTROL_JAVASP_STOP || + opcode == SERVICE_CONTROL_PL_START || + opcode == SERVICE_CONTROL_PL_STOP || opcode == SERVICE_CONTROL_BROKER_ON || opcode == SERVICE_CONTROL_BROKER_OFF || opcode == SERVICE_CONTROL_GATEWAY_ON || opcode == SERVICE_CONTROL_GATEWAY_OFF) diff --git a/src/method/method_compile.hpp b/src/xasl/xasl_sp.hpp similarity index 52% rename from src/method/method_compile.hpp rename to src/xasl/xasl_sp.hpp index 554abe55065..9b77313d6eb 100644 --- a/src/method/method_compile.hpp +++ b/src/xasl/xasl_sp.hpp @@ -17,29 +17,31 @@ */ // -// method_compile.hpp - define structures used by method feature +// xasl_sp.hpp - XASL structures used for stored procedures // -#ifndef _METHOD_COMPILE_HPP_ -#define _METHOD_COMPILE_HPP_ +#ifndef _XASL_STORED_PROCEDURE_HPP_ +#define _XASL_STORED_PROCEDURE_HPP_ -#include "mem_block.hpp" +#include "dbtype_def.h" +#include "storage_common.h" +#include "pl_signature.hpp" -#if defined (SERVER_MODE) || defined (SA_MODE) -#include "method_invoke.hpp" -#include "method_runtime_context.hpp" -#endif +// forward definitions +struct regu_variable_list_node; +class regu_variable_node; -#include -#include - -namespace cubmethod +namespace cubxasl { -#if defined (SERVER_MODE) || defined (SA_MODE) - int invoke_compile (cubthread::entry &thread, runtime_context &ctx, const std::string &program, - const bool &verbose, - cubmem::extensible_block &blk); -#endif -} + struct sp_node + { + cubpl::pl_signature *sig; + regu_variable_list_node *args; + DB_VALUE *value; // return value + }; +}; + +// legacy aliases +using SP_TYPE = cubxasl::sp_node; -#endif //_METHOD_COMPILE_HPP_ +#endif // _XASL_STORED_PROCEDURE_HPP_ diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index 3d8f74f76f6..d1d36b26d47 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -96,7 +96,6 @@ set(CUB_MASTER_SOURCES ) if(UNIX) list(APPEND CUB_MASTER_SOURCES ${EXECUTABLES_DIR}/master_heartbeat.c) - list(APPEND CUB_MASTER_SOURCES ${EXECUTABLES_DIR}/master_server_monitor.cpp) SET_SOURCE_FILES_PROPERTIES( ${CUB_MASTER_SOURCES} PROPERTIES LANGUAGE CXX @@ -221,18 +220,20 @@ else(UNIX) target_link_libraries(loadjava LINK_PRIVATE cubridcs) endif(UNIX) -set(JAVASP_SERVER_SOURCES - ${EXECUTABLES_DIR}/javasp.cpp +set(PL_SERVER_SOURCES + ${EXECUTABLES_DIR}/pl.cpp ) SET_SOURCE_FILES_PROPERTIES( - ${JAVASP_SERVER_SOURCES} + ${PL_SERVER_SOURCES} PROPERTIES LANGUAGE CXX ) if(WIN32) - list(APPEND JAVASP_SERVER_SOURCES ${CMAKE_BINARY_DIR}/version.rc) + list(APPEND PL_SERVER_SOURCES ${CMAKE_BINARY_DIR}/version.rc) endif(WIN32) -add_executable(cub_javasp ${JAVASP_SERVER_SOURCES}) -target_link_libraries(cub_javasp LINK_PRIVATE cubridsa) +add_executable(cub_pl ${PL_SERVER_SOURCES}) +target_include_directories(cub_pl PRIVATE ${JAVA_INC} ${CMAKE_BINARY_DIR} ${EP_INCLUDES}) +target_compile_definitions(cub_pl PRIVATE PL_MODE ${COMMON_DEFS}) +target_link_libraries(cub_pl LINK_PRIVATE cubridsa) set(CUB_ADMIN_SOURCES ${EXECUTABLES_DIR}/util_admin.c @@ -385,7 +386,7 @@ install(TARGETS cub_commdb cubrid_rel loadjava - cub_javasp + cub_pl cub_admin cubrid_esql plcsql_helper diff --git a/win/cubridcs/cubridcs.def b/win/cubridcs/cubridcs.def index 8061507902b..ac18a59f9dc 100644 --- a/win/cubridcs/cubridcs.def +++ b/win/cubridcs/cubridcs.def @@ -979,3 +979,7 @@ EXPORTS gethostbyname_uhost getnameinfo_uhost trim + er_has_error + prm_get_name + windows_socket_startup + windows_socket_shutdown diff --git a/win/cubridsa/cubridsa.def b/win/cubridsa/cubridsa.def index de412f9bcfe..c1d922ba23e 100644 --- a/win/cubridsa/cubridsa.def +++ b/win/cubridsa/cubridsa.def @@ -132,20 +132,20 @@ EXPORTS er_init er_final er_clear - jsp_connect_server - jsp_disconnect_server - jsp_writen - jsp_readn - jsp_start_server - jsp_server_port - javasp_get_info_file - javasp_get_error_file - javasp_open_info_dir - javasp_open_info - javasp_read_info - javasp_reset_info - javasp_write_info - javasp_unlink_info + pl_connect_server + pl_disconnect_server + pl_writen + pl_readn + pl_start_jvm_server + pl_server_port + pl_get_info_file + pl_get_error_file + pl_open_info_dir + pl_open_info + pl_read_info + pl_reset_info + pl_write_info + pl_unlink_info ; ; utility functions ;