{"id":7254,"date":"2016-09-25T23:21:21","date_gmt":"2016-09-25T21:21:21","guid":{"rendered":"https:\/\/www.salvis.com\/blog\/?p=7254"},"modified":"2023-11-07T23:09:22","modified_gmt":"2023-11-07T22:09:22","slug":"bitemp-remodeler-v0-1-0-released","status":"publish","type":"post","link":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/","title":{"rendered":"Bitemp Remodeler v0.1.0 Released"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I&#8217;ve been working on a flexible table API generator for Oracle Databases for several months. A\u00a0TAPI generator doesn&#8217;t sound like a real innovation. But this one contains some features you probably have not\u00a0seen before in the TAPI generator and hopefully\u00a0will like it as much as I do.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this post, I will not explain the feature set thoroughly. Instead, I will more or less focus on one of my favourite features.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Four models<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The generator knows the following four data models.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models.png\"><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" width=\"1424\" height=\"643\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models.png\" alt=\"four_models\" class=\"wp-image-7258\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models.png 1424w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models-300x135.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models-768x347.png 768w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models-1024x462.png 1024w\" sizes=\"auto, (max-width:767px) 480px, (max-width:1424px) 100vw, 1424px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If your table is based on one of these four models you may<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>simply generate a table API for it&nbsp;or<\/li>\n\n\n\n<li>switch to another model and optionally generate a table API as well.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Option 2) is extraordinary, since it will preserve the existing data. E.g. it will preserve the content of the flashback data archive when you switch your model from uni-temporal transaction time to a bi-temporal model even if the flashback archive tables need to be moved\u00a0to\u00a0another table. Furthermore, it will keep the interface for the latest table the same. No application change is required. Everything with just a few mouse clicks. If this sounds interesting to you, then have a look at\u00a0https:\/\/github.com\/oddgen\/bitemp\/blob\/main\/README.md where the concept is briefly explained or join me in my session &#8220;oddgen &#8211; Bi-temporal Table API in Action&#8221; at the <a href=\"http:\/\/www.trivadis.com\/en\/training\/more-just-performance-days-2016-tvdpdays\">More than just \u2013 Performance Days 2016<\/a>. Remote participation is still possible.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Option 1) is what we had for years. It was part of Oracle Designer, it&#8217;s part of SQL Developer in a simplified way and there are some more\u00a0or less simple table API generators around. So no big deal. However, when you choose option 1), there is one cool part. The hook API package concept.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Hook API<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The problem with a lot of table API solutions is, that there is typically no developer-friendly way to include the\u00a0business logic. I&#8217;ve seen the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Manual changes of the generated code, which is for various reasons not a good solution.<\/li>\n\n\n\n<li>External hooks, e.g. in XML files, INI files, relational tables, etc. and merged at generation time into the final code. Oracle Designer worked that way.<\/li>\n\n\n\n<li>Code which is dynamically executed by the generator at runtime, e.g. code snippets is stored in a pre-defined way in relational tables.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">But what I&#8217;ve never seen, was business logic implemented in manually crafted PL\/SQL packages, separated from the PL\/SQL generated code. That&#8217;s strange\u00a0because this is a common practice in Java-based projects.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In Java, you typically define an interface for that and configure\u00a0at runtime the right implementation. In PL\/SQL we may do that similarly. A PL\/SQL specification is\u00a0an interface definition. That just one implementation may exist for\u00a0an interface\u00a0is not a limiting factor in this case.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bitemp Remodeler generates the following hook API package specification for the famous EMP&nbsp;table in schema SCOTT:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Package specification EMP_HOOK<\/span><span role=\"button\" tabindex=\"0\" data-code=\"CREATE OR REPLACE PACKAGE emp_hook AS\n   \/** \n   * Hooks called by non-temporal API for table emp_lt (see package body of emp_api)\n   * generated by Bitemp Remodeler for SQL Developer.\n   * The body of this package is not generated. It has to be crafted and maintained manually. \n   * Since the API for table emp_lt ignores errors caused by a missing hook package body, the implementation is optional.\n   *\n   * @headcom\n   *\/\n\n   \/**\n   * Hook called before insert into non-temporal table emp_lt.\n   *\n   * @param io_new_row new Row to be inserted\n   *\/\n   PROCEDURE pre_ins (\n      io_new_row IN OUT emp_ot\n   );\n\n   \/**\n   * Hook called after insert into non-temporal table emp_lt.\n   *\n   * @param in_new_row new Row to be inserted\n   *\/\n   PROCEDURE post_ins (\n      in_new_row IN emp_ot\n   );\n\n   \/**\n   * Hook called before update non-temporal table emp_lt.\n   *\n   * @param io_new_row Row with updated column values\n   * @param in_old_row Row with original column values\n   *\/\n   PROCEDURE pre_upd (\n      io_new_row IN OUT emp_ot,\n      in_old_row IN emp_ot\n   );\n\n   \/**\n   * Hook called after update non-temporal table emp_lt.\n   *\n   * @param in_new_row Row with updated column values\n   * @param in_old_row Row with original column values\n   *\/\n   PROCEDURE post_upd (\n      in_new_row IN emp_ot,\n      in_old_row IN emp_ot\n   );\n\n   \/**\n   * Hook called before delete from non-temporal table emp_lt.\n   *\n   * @param in_old_row Row with original column values\n   *\/\n   PROCEDURE pre_del (\n      in_old_row IN emp_ot\n   );\n\n   \/**\n   * Hook called after delete from non-temporal table emp_lt.\n   *\n   * @param in_old_row Row with original column values\n   *\/\n   PROCEDURE post_del (\n      in_old_row IN emp_ot\n   );\n\nEND emp_hook;\n\/\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">CREATE OR REPLACE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">PACKAGE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">emp_hook<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">AS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #6A9955\">\/** <\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * Hooks called by non-temporal API for table emp_lt (see package body of emp_api)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * generated by Bitemp Remodeler for SQL Developer.<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #6A9955\">   * The body of this package is not generated. It has to be crafted and maintained manually. <\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #6A9955\">   * Since the API for table emp_lt ignores errors caused by a missing hook package body, the implementation is optional.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * @headcom<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * Hook called before insert into non-temporal table emp_lt.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * @param io_new_row new Row to be inserted<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">PROCEDURE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">pre_ins<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      io_new_row <\/span><span style=\"color: #569CD6\">IN<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">OUT<\/span><span style=\"color: #D4D4D4\"> emp_ot<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   );<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * Hook called after insert into non-temporal table emp_lt.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * @param in_new_row new Row to be inserted<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">PROCEDURE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">post_ins<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      in_new_row <\/span><span style=\"color: #569CD6\">IN<\/span><span style=\"color: #D4D4D4\"> emp_ot<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   );<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * Hook called before update non-temporal table emp_lt.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * @param io_new_row Row with updated column values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * @param in_old_row Row with original column values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">PROCEDURE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">pre_upd<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      io_new_row <\/span><span style=\"color: #569CD6\">IN<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">OUT<\/span><span style=\"color: #D4D4D4\"> emp_ot,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      in_old_row <\/span><span style=\"color: #569CD6\">IN<\/span><span style=\"color: #D4D4D4\"> emp_ot<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   );<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * Hook called after update non-temporal table emp_lt.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * @param in_new_row Row with updated column values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * @param in_old_row Row with original column values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">PROCEDURE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">post_upd<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      in_new_row <\/span><span style=\"color: #569CD6\">IN<\/span><span style=\"color: #D4D4D4\"> emp_ot,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      in_old_row <\/span><span style=\"color: #569CD6\">IN<\/span><span style=\"color: #D4D4D4\"> emp_ot<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   );<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * Hook called before delete from non-temporal table emp_lt.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * @param in_old_row Row with original column values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">PROCEDURE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">pre_del<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      in_old_row <\/span><span style=\"color: #569CD6\">IN<\/span><span style=\"color: #D4D4D4\"> emp_ot<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   );<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * Hook called after delete from non-temporal table emp_lt.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   * @param in_old_row Row with original column values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">   *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">PROCEDURE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">post_del<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      in_old_row <\/span><span style=\"color: #569CD6\">IN<\/span><span style=\"color: #D4D4D4\"> emp_ot<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   );<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">END<\/span><span style=\"color: #D4D4D4\"> emp_hook;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The generated table API calls before an INSERT the pre_ins procedure and after the INSERT the post_ins procedures. For DELETE and UPDATE this works the same way. On the highlighted line 5 and 6 two interested things are pointed out. The body is not generated and the body does not need to be implemented since the API ignores errors caused by a missing PL\/SQL hook package body.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Technically this is solved as follows in the API package body:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-start:16;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Excerpt 1 of package body EMP_API<\/span><span role=\"button\" tabindex=\"0\" data-code=\"   e_hook_body_missing EXCEPTION;\n   PRAGMA exception_init(e_hook_body_missing, -6508);\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">   e_hook_body_missing <\/span><span style=\"color: #569CD6\">EXCEPTION<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">PRAGMA exception_init<\/span><span style=\"color: #D4D4D4\">(e_hook_body_missing, -<\/span><span style=\"color: #B5CEA8\">6508<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-start:167;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Excerpt 2 of package body EMP_API<\/span><span role=\"button\" tabindex=\"0\" data-code=\"      &lt;&lt;pre_ins&gt;&gt;\n      BEGIN\n         emp_hook.pre_ins(io_new_row =&gt; l_new_row);\n      EXCEPTION\n         WHEN e_hook_body_missing THEN\n            NULL;\n      END pre_ins;\n      do_ins(io_row =&gt; l_new_row);\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">      &lt;&lt;pre_ins&gt;&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">BEGIN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         emp_hook.pre_ins(io_new_row =&gt; <\/span><span style=\"color: #9CDCFE\">l_new_row<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">EXCEPTION<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         <\/span><span style=\"color: #569CD6\">WHEN<\/span><span style=\"color: #D4D4D4\"> e_hook_body_missing <\/span><span style=\"color: #569CD6\">THEN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">NULL<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">END<\/span><span style=\"color: #D4D4D4\"> pre_ins;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      do_ins(io_row =&gt; <\/span><span style=\"color: #9CDCFE\">l_new_row<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Now you may ask what the performance impact of these e_hook_body_missing exceptions are. I&#8217;ve done a small test and called a procedure without and with implemented body 1 million times. The overhead of the missing body exception is about 7 microseconds per call. Here&#8217;s the test output from SQL Developer, the relevant lines 51 and 89 are highlighted.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Overhead of missing package body<\/span><span role=\"button\" tabindex=\"0\" data-code=\"SQL&gt; SET FEEDBACK ON\nSQL&gt; SET ECHO ON\nSQL&gt; SET TIMING ON\nSQL&gt; DROP PACKAGE dummy_api;\n\nPackage DUMMY_API dropped.\n\nElapsed: 00:00:00.027\nSQL&gt; DROP PACKAGE dummy_hook;\n\nPackage DUMMY_HOOK dropped.\n\nElapsed: 00:00:00.030\nSQL&gt; CREATE OR REPLACE PACKAGE dummy_hook AS\n   PROCEDURE pre_ins;\nEND dummy_hook;\n\/\n\nPackage DUMMY_HOOK compiled\n\nElapsed: 00:00:00.023\nSQL&gt; CREATE OR REPLACE PACKAGE dummy_api AS\n   PROCEDURE ins;\nEND dummy_api;\n\/\n\nPackage DUMMY_API compiled\n\nElapsed: 00:00:00.034\nSQL&gt; CREATE OR REPLACE PACKAGE BODY dummy_api AS\n   e_hook_body_missing EXCEPTION;\n   PRAGMA exception_init(e_hook_body_missing, -6508);  \n   PROCEDURE ins IS\n   BEGIN\n      BEGIN\n         dummy_hook.pre_ins;\n      EXCEPTION\n         WHEN e_hook_body_missing THEN\n            NULL;\n      END pre_ins;\n      dbms_output.put('.');\n   END ins;\nEND dummy_api;\n\/\n\nPackage body DUMMY_API compiled\n\nElapsed: 00:00:00.040\nSQL&gt; -- without hook body\nSQL&gt; BEGIN\n   FOR i IN 1..1E6 LOOP\n      dummy_api.ins;\n   END LOOP;\nEND;\n\/\n\nPL\/SQL procedure successfully completed.\n\nElapsed: 00:00:07.878\nSQL&gt; CREATE OR REPLACE PACKAGE BODY dummy_hook AS\n   PROCEDURE pre_ins IS\n   BEGIN\n      dbms_output.put('-');\n   END pre_ins;\nEND dummy_hook;\n\/\n\nPackage body DUMMY_HOOK compiled\n\nElapsed: 00:00:00.029\nSQL&gt; -- with hook body\nSQL&gt; BEGIN\n   FOR i IN 1..1E6 LOOP\n      dummy_api.ins;\n   END LOOP;\nEND;\n\/\n\nPL\/SQL procedure successfully completed.\n\nElapsed: 00:00:00.632\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; SET FEEDBACK ON<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; SET ECHO ON<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; SET TIMING ON<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; DROP PACKAGE dummy_api;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Package DUMMY_API dropped.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Elapsed: 00:00:00.027<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; DROP PACKAGE dummy_hook;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Package DUMMY_HOOK dropped.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Elapsed: 00:00:00.030<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; CREATE OR REPLACE PACKAGE dummy_hook AS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   PROCEDURE pre_ins;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">END dummy_hook;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Package DUMMY_HOOK compiled<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Elapsed: 00:00:00.023<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; CREATE OR REPLACE PACKAGE dummy_api AS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   PROCEDURE ins;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">END dummy_api;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Package DUMMY_API compiled<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Elapsed: 00:00:00.034<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; CREATE OR REPLACE PACKAGE BODY dummy_api AS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   e_hook_body_missing EXCEPTION;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   PRAGMA exception_init(e_hook_body_missing, -6508);  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   PROCEDURE ins IS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   BEGIN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      BEGIN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         dummy_hook.pre_ins;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      EXCEPTION<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         WHEN e_hook_body_missing THEN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            NULL;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      END pre_ins;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      dbms_output.put(&#39;.&#39;);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   END ins;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">END dummy_api;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Package body DUMMY_API compiled<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Elapsed: 00:00:00.040<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; -- without hook body<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; BEGIN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   FOR i IN 1..1E6 LOOP<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      dummy_api.ins;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   END LOOP;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">END;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">PL\/SQL procedure successfully completed.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">Elapsed: 00:00:07.878<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; CREATE OR REPLACE PACKAGE BODY dummy_hook AS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   PROCEDURE pre_ins IS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   BEGIN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      dbms_output.put(&#39;-&#39;);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   END pre_ins;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">END dummy_hook;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Package body DUMMY_HOOK compiled<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Elapsed: 00:00:00.029<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; -- with hook body<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; BEGIN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   FOR i IN 1..1E6 LOOP<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      dummy_api.ins;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   END LOOP;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">END;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">PL\/SQL procedure successfully completed.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">Elapsed: 00:00:00.632<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">It\u00a0makes sense to provide a body with a NULL implementation to avoid the small overhead of handling the missing body exception.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nonetheless,\u00a0the way the business logic is separated from the generated code is one of the many things I like about Bitemp Remodeler.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Download Bitemp Remodeler from the&nbsp;<a href=\"https:\/\/www.salvis.com\/blog\/download\/\">Download<\/a> section on&nbsp;my blog or install it directly via the SQL Developer update site <a href=\"http:\/\/update.oddgen.org\/\">http:\/\/update.oddgen.org\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been working on a flexible table API generator for Oracle Databases for several months. A\u00a0TAPI generator doesn&#8217;t sound like a real innovation. But this one contains some features you probably have not\u00a0seen before in the TAPI generator and hopefully\u00a0will like it as much as I do. In this post, I will<span class=\"excerpt-hellip\"> [\u2026]<\/span><\/p>\n","protected":false},"author":1,"featured_media":7258,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[50,68,94,13,85,87,42,49,43],"class_list":["post-7254","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle","tag-flashback","tag-flashback-data-archive","tag-oddgen","tag-plsql","tag-sql","tag-sql-developer","tag-temporal-database","tag-transaction-time","tag-valid-time"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Bitemp Remodeler v0.1.0 Released - Philipp Salvisberg&#039;s Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Bitemp Remodeler v0.1.0 Released - Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"I&#8217;ve been working on a flexible table API generator for Oracle Databases for several months. A\u00a0TAPI generator doesn&#8217;t sound like a real innovation. But this one contains some features you probably have not\u00a0seen before in the TAPI generator and hopefully\u00a0will like it as much as I do. In this post, I will [\u2026]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/\" \/>\n<meta property=\"og:site_name\" content=\"Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2016-09-25T21:21:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-07T22:09:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1424\" \/>\n\t<meta property=\"og:image:height\" content=\"643\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Philipp Salvisberg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:site\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Philipp Salvisberg\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/\"},\"author\":{\"name\":\"Philipp Salvisberg\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"headline\":\"Bitemp Remodeler v0.1.0 Released\",\"datePublished\":\"2016-09-25T21:21:21+00:00\",\"dateModified\":\"2023-11-07T22:09:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/\"},\"wordCount\":727,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/09\\\/four_models.png\",\"keywords\":[\"Flashback\",\"Flashback Data Archive\",\"oddgen\",\"PL\\\/SQL\",\"SQL\",\"SQL Developer\",\"Temporal Database\",\"Transaction Time\",\"Valid Time\"],\"articleSection\":[\"Oracle\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/\",\"name\":\"Bitemp Remodeler v0.1.0 Released - Philipp Salvisberg&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/09\\\/four_models.png\",\"datePublished\":\"2016-09-25T21:21:21+00:00\",\"dateModified\":\"2023-11-07T22:09:22+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/09\\\/four_models.png\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/09\\\/four_models.png\",\"width\":1424,\"height\":643},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2016\\\/09\\\/25\\\/bitemp-remodeler-v0-1-0-released\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Bitemp Remodeler v0.1.0 Released\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\",\"name\":\"Philipp Salvisberg&#039;s Blog\",\"description\":\"Database-centric development\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\",\"name\":\"Philipp Salvisberg\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"width\":400,\"height\":400,\"caption\":\"Philipp Salvisberg\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\"},\"sameAs\":[\"http:\\\/\\\/www.salvis.com\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Bitemp Remodeler v0.1.0 Released - Philipp Salvisberg&#039;s Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/","og_locale":"en_US","og_type":"article","og_title":"Bitemp Remodeler v0.1.0 Released - Philipp Salvisberg&#039;s Blog","og_description":"I&#8217;ve been working on a flexible table API generator for Oracle Databases for several months. A\u00a0TAPI generator doesn&#8217;t sound like a real innovation. But this one contains some features you probably have not\u00a0seen before in the TAPI generator and hopefully\u00a0will like it as much as I do. In this post, I will [\u2026]","og_url":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/","og_site_name":"Philipp Salvisberg&#039;s Blog","article_published_time":"2016-09-25T21:21:21+00:00","article_modified_time":"2023-11-07T22:09:22+00:00","og_image":[{"width":1424,"height":643,"url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models.png","type":"image\/png"}],"author":"Philipp Salvisberg","twitter_card":"summary_large_image","twitter_creator":"@phsalvisberg","twitter_site":"@phsalvisberg","twitter_misc":{"Written by":"Philipp Salvisberg","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/#article","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/"},"author":{"name":"Philipp Salvisberg","@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"headline":"Bitemp Remodeler v0.1.0 Released","datePublished":"2016-09-25T21:21:21+00:00","dateModified":"2023-11-07T22:09:22+00:00","mainEntityOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/"},"wordCount":727,"commentCount":0,"publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models.png","keywords":["Flashback","Flashback Data Archive","oddgen","PL\/SQL","SQL","SQL Developer","Temporal Database","Transaction Time","Valid Time"],"articleSection":["Oracle"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/","url":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/","name":"Bitemp Remodeler v0.1.0 Released - Philipp Salvisberg&#039;s Blog","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/#primaryimage"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models.png","datePublished":"2016-09-25T21:21:21+00:00","dateModified":"2023-11-07T22:09:22+00:00","breadcrumb":{"@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/#primaryimage","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models.png","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2016\/09\/four_models.png","width":1424,"height":643},{"@type":"BreadcrumbList","@id":"https:\/\/www.salvis.com\/blog\/2016\/09\/25\/bitemp-remodeler-v0-1-0-released\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.salvis.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Bitemp Remodeler v0.1.0 Released"}]},{"@type":"WebSite","@id":"https:\/\/www.salvis.com\/blog\/#website","url":"https:\/\/www.salvis.com\/blog\/","name":"Philipp Salvisberg&#039;s Blog","description":"Database-centric development","publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.salvis.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515","name":"Philipp Salvisberg","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","width":400,"height":400,"caption":"Philipp Salvisberg"},"logo":{"@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg"},"sameAs":["http:\/\/www.salvis.com\/"]}]}},"_links":{"self":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/7254","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/comments?post=7254"}],"version-history":[{"count":29,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/7254\/revisions"}],"predecessor-version":[{"id":12602,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/7254\/revisions\/12602"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media\/7258"}],"wp:attachment":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media?parent=7254"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/categories?post=7254"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/tags?post=7254"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}