{"id":6417,"date":"2017-02-08T11:03:35","date_gmt":"2017-02-08T16:03:35","guid":{"rendered":"https:\/\/www.caskeys.com\/dc\/?p=6417"},"modified":"2026-05-18T14:14:58","modified_gmt":"2026-05-18T18:14:58","slug":"dynamic-stored-procedure-call-generation","status":"publish","type":"post","link":"https:\/\/www.caskeys.com\/dc\/dynamic-stored-procedure-call-generation\/","title":{"rendered":"Dynamic Stored Procedure Call Generation"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Scripting experiment. Inspector Blair page layout is currently static code. I would like to upgrade to a content managed layout. One of the first challenges is overcoming the diverse array of forms and subsequent data calls. Dynamic queries are NOT acceptable &#8211; I&#8217;d rather do {some unpleasant thing} than code one line of that nonsense. Same goes for handing it over to an ORM. Instead I&#8217;ll attempt to assemble known stored procedure calls from trusted form metadata. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This experiment was to test a simple array generator. Normally saving to the database is handled by a set of class calls as in this excerpt:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\ncase RECORD_NAV_COMMANDS::SAVE:\n     \n    \/\/ Stop errors in case someone tries a direct command link.\n    if($obj_navigation_rec-&gt;get_command() != RECORD_NAV_COMMANDS::SAVE) break;\n                             \n    \/\/ Save the record. Saving main record is straightforward. We\u2019ll run the populate method on our \n    \/\/ main data object which will gather up post values. Then we can run a query to merge the values into \n    \/\/ database table. We\u2019ll then get the id from saved record (since we are using a surrogate key, the ID\n    \/\/ should remain static unless this is a brand new record). \n     \n    \/\/ If necessary we will then save any sub records (see each for details).\n     \n    \/\/ Finally, we redirect to the current page using the freshly acquired id. \n    \/\/ That will ensure we always have an up-to-date ID for our forms and navigation system.         \n \n    \/\/ Populate the object from post values.            \n    $_main_data-&gt;populate_from_request();\n     \n    \/\/ --Sub data: Role.\n    $_obj_data_sub_request = new class_account_role_data();\n    $_obj_data_sub_request-&gt;populate_from_request();\n \n    \/\/ Let&#039;s get account info from the active directory system. We&#039;ll need to put\n    \/\/ names in our own database so we can control ordering of output.\n    $account_lookup = new class_access_lookup();\n    $account_lookup-&gt;lookup($_main_data-&gt;get_account());\n \n    \/\/ Call update stored procedure.\n    $query-&gt;set_sql(&#039;{call account_update(@id            = ?,\n                                            @log_update_by  = ?, \n                                            @log_update_ip  = ?,                                         \n                                            @account        = ?,\n                                            @department     = ?,\n                                            @details        = ?,\n                                            @name_f         = ?,\n                                            @name_l         = ?,\n                                            @name_m         = ?,\n                                            @sub_role_xml   = ?)}&#039;);\n                                             \n    $params = array(array(&#039;&lt;root&gt;&lt;row id=&quot;&#039;.$_main_data-&gt;get_id().&#039;&quot;\/&gt;&lt;\/root&gt;&#039;,        SQLSRV_PARAM_IN),\n                array($access_obj-&gt;get_id(),                 SQLSRV_PARAM_IN),\n                array($access_obj-&gt;get_ip(),             SQLSRV_PARAM_IN),\n                array($_main_data-&gt;get_account(),        SQLSRV_PARAM_IN),                       \n                array($_main_data-&gt;get_department(), SQLSRV_PARAM_IN),                       \n                array($_main_data-&gt;get_details(),        SQLSRV_PARAM_IN),\n                array($account_lookup-&gt;get_account_data()-&gt;get_name_f(), SQLSRV_PARAM_IN),\n                array($account_lookup-&gt;get_account_data()-&gt;get_name_l(), SQLSRV_PARAM_IN),\n                array($account_lookup-&gt;get_account_data()-&gt;get_name_m(), SQLSRV_PARAM_IN),\n                array($_obj_data_sub_request-&gt;xml(),     SQLSRV_PARAM_IN));\n     \n    \/\/var_dump($params);\n    \/\/exit;\n     \n    $query-&gt;set_params($params);         \n    $query-&gt;query();\n     \n    \/\/ Repopulate main data object with results from merge query.\n    $query-&gt;get_line_params()-&gt;set_class_name(&#039;blair_class_account_data&#039;);\n    $_main_data = $query-&gt;get_line_object();\n     \n    \/\/ Now that save operation has completed, reload page using ID from\n    \/\/ database. This ensures the ID is always up to date, even with a new\n    \/\/ or copied record.\n    header(&#039;Location: &#039;.$_SERVER&#x5B;&#039;PHP_SELF&#039;].&#039;?id=&#039;.$_main_data-&gt;get_id());\n     \n    break;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Before we can begin to control the above calls dynamically, we&#8217;ll need to break the call down and see if we can assemble the sql string. Here we will concentrate on building the SQL string.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The form parts and column names they send data to will likely be stored in a sub-table of the forms database, and output as a linked list. We need to use those column names in a call string for sending or retrieving data. This simple experiment uses a keyed array to simulate the list we might get and see if we can concatenate a usable stored procedure call string.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\n$_main_data-&gt;populate_from_request();\n             \n\/\/ --Sub data: Role.\n$_obj_data_sub_request = new class_account_role_data();\n$_obj_data_sub_request-&gt;populate_from_request();\n \n\/\/ Let&#039;s get account info from the active directory system. We&#039;ll need to put\n\/\/ names in our own database so we can control ordering of output.\n$account_lookup = new class_access_lookup();\n$account_lookup-&gt;lookup($_main_data-&gt;get_account());\n \n$save_row&#x5B;&#039;id&#039;]                = &#039;&lt;root&gt;&lt;row id=&quot;&#039;.$_main_data-&gt;get_id().&#039;&quot;\/&gt;&lt;\/root&gt;&#039;;\n$save_row&#x5B;&#039;log_update_by&#039;]    = $access_obj-&gt;get_id();\n$save_row&#x5B;&#039;log_update_ip&#039;]     = $access_obj-&gt;get_ip();\n$save_row&#x5B;&#039;account&#039;]         = $_main_data-&gt;get_account();\n$save_row&#x5B;&#039;department&#039;]        = $_main_data-&gt;get_department();\n$save_row&#x5B;&#039;name_f&#039;]         = $account_lookup-&gt;get_account_data()-&gt;get_name_f();\n$save_row&#x5B;&#039;name_l&#039;]         = $account_lookup-&gt;get_account_data()-&gt;get_name_l();\n$save_row&#x5B;&#039;name_m&#039;]         = $account_lookup-&gt;get_account_data()-&gt;get_name_m();    \n$save_row&#x5B;&#039;sub_role_xml&#039;]     = $_obj_data_sub_request-&gt;xml();        \n \n$sql_str = &#039;{call account_update(@&#039;;\n$sql_str .= implode(&#039; = ?, @&#039;, array_keys($save_row));\n$sql_str .= &#039; = ?)}&#039;;\necho $sql_str;\n \n\/\/\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Obviously this alone won&#8217;t be enough, but the resulting output looks quite promising:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: Code:; notranslate\" title=\"Code:\">\n{call account_update(@id = ?, @log_update_by = ?, @log_update_ip = ?, @account = ?, @department = ?, @name_f = ?, @name_l = ?, @name_m = ?, @sub_role_xml = ?)}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Working on dynamically built stored procedure calls.<\/p>\n","protected":false},"author":1,"featured_media":6216,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[71],"tags":[27,269,234,298,286],"class_list":["post-6417","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology-temerity","tag-coding","tag-applications-inspector-blair","tag-coding-php","tag-technology-temerity","tag-uk-ehs"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2016\/06\/logo-php.png","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5lNM5-1Fv","jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/6417","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/comments?post=6417"}],"version-history":[{"count":9,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/6417\/revisions"}],"predecessor-version":[{"id":7955,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/6417\/revisions\/7955"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/media\/6216"}],"wp:attachment":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/media?parent=6417"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/categories?post=6417"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/tags?post=6417"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}