{"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":"2017-02-08T11:54:56","modified_gmt":"2017-02-08T16:54:56","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":"<p>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. Instead I&#8217;ll need to find a way to create dynamic inputs for stored procedures that can be driven from a forms database.<\/p>\n<p>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<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\ncase RECORD_NAV_COMMANDS::SAVE:\r\n\t\r\n\t\/\/ Stop errors in case someone tries a direct command link.\r\n\tif($obj_navigation_rec-&gt;get_command() != RECORD_NAV_COMMANDS::SAVE) break;\r\n\t\t\t\t\t\t\t\r\n\t\/\/ Save the record. Saving main record is straight forward. We\u2019ll run the populate method on our \r\n\t\/\/ main data object which will gather up post values. Then we can run a query to merge the values into \r\n\t\/\/ database table. We\u2019ll then get the id from saved record (since we are using a surrogate key, the ID\r\n\t\/\/ should remain static unless this is a brand new record). \r\n\t\r\n\t\/\/ If necessary we will then save any sub records (see each for details).\r\n\t\r\n\t\/\/ Finally, we redirect to the current page using the freshly acquired id. That will ensure we have \r\n\t\/\/ always an up to date ID for our forms and navigation system.\t\t\t\r\n\r\n\t\/\/ Populate the object from post values.\t\t\t\r\n\t$_main_data-&gt;populate_from_request();\r\n\t\r\n\t\/\/ --Sub data: Role.\r\n\t$_obj_data_sub_request = new class_account_role_data();\r\n\t$_obj_data_sub_request-&gt;populate_from_request();\r\n\r\n\t\/\/ Let's get account info from the active directory system. We'll need to put\r\n\t\/\/ names int our own database so we can control ordering of output.\r\n\t$account_lookup = new class_access_lookup();\r\n\t$account_lookup-&gt;lookup($_main_data-&gt;get_account());\r\n\r\n\t\/\/ Call update stored procedure.\r\n\t$query-&gt;set_sql('{call account_update(@id\t\t\t= ?,\r\n\t\t\t\t\t\t\t\t\t\t\t@log_update_by\t= ?, \r\n\t\t\t\t\t\t\t\t\t\t\t@log_update_ip \t= ?,\t\t\t\t\t\t\t\t\t\t \r\n\t\t\t\t\t\t\t\t\t\t\t@account \t\t= ?,\r\n\t\t\t\t\t\t\t\t\t\t\t@department \t= ?,\r\n\t\t\t\t\t\t\t\t\t\t\t@details\t\t= ?,\r\n\t\t\t\t\t\t\t\t\t\t\t@name_f\t\t\t= ?,\r\n\t\t\t\t\t\t\t\t\t\t\t@name_l\t\t\t= ?,\r\n\t\t\t\t\t\t\t\t\t\t\t@name_m\t\t\t= ?,\r\n\t\t\t\t\t\t\t\t\t\t\t@sub_role_xml\t= ?)}');\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t$params = array(array('&lt;root&gt;&lt;row id=&quot;'.$_main_data-&gt;get_id().'&quot;\/&gt;&lt;\/root&gt;', \t\tSQLSRV_PARAM_IN),\r\n\t\t\t\tarray($access_obj-&gt;get_id(), \t\t\t\tSQLSRV_PARAM_IN),\r\n\t\t\t\tarray($access_obj-&gt;get_ip(), \t\t\tSQLSRV_PARAM_IN),\r\n\t\t\t\tarray($_main_data-&gt;get_account(), \t\tSQLSRV_PARAM_IN),\t\t\t\t\t\t\r\n\t\t\t\tarray($_main_data-&gt;get_department(),\tSQLSRV_PARAM_IN),\t\t\t\t\t\t\r\n\t\t\t\tarray($_main_data-&gt;get_details(), \t\tSQLSRV_PARAM_IN),\r\n\t\t\t\tarray($account_lookup-&gt;get_account_data()-&gt;get_name_f(), SQLSRV_PARAM_IN),\r\n\t\t\t\tarray($account_lookup-&gt;get_account_data()-&gt;get_name_l(), SQLSRV_PARAM_IN),\r\n\t\t\t\tarray($account_lookup-&gt;get_account_data()-&gt;get_name_m(), SQLSRV_PARAM_IN),\r\n\t\t\t\tarray($_obj_data_sub_request-&gt;xml(), \tSQLSRV_PARAM_IN));\r\n\t\r\n\t\/\/var_dump($params);\r\n\t\/\/exit;\r\n\t\r\n\t$query-&gt;set_params($params);\t\t\t\r\n\t$query-&gt;query();\r\n\t\r\n\t\/\/ Repopulate main data object with results from merge query.\r\n\t$query-&gt;get_line_params()-&gt;set_class_name('blair_class_account_data');\r\n\t$_main_data = $query-&gt;get_line_object();\r\n\t\r\n\t\/\/ Now that save operation has completed, reload page using ID from\r\n\t\/\/ database. This ensures the ID is always up to date, even with a new\r\n\t\/\/ or copied record.\r\n\theader('Location: '.$_SERVER&#x5B;'PHP_SELF'].'?id='.$_main_data-&gt;get_id());\r\n\t\r\n\tbreak;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>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<p>The form parts and column names they send data too 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<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\n$_main_data-&gt;populate_from_request();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\/\/ --Sub data: Role.\r\n$_obj_data_sub_request = new class_account_role_data();\r\n$_obj_data_sub_request-&gt;populate_from_request();\r\n\r\n\/\/ Let's get account info from the active directory system. We'll need to put\r\n\/\/ names int our own database so we can control ordering of output.\r\n$account_lookup = new class_access_lookup();\r\n$account_lookup-&gt;lookup($_main_data-&gt;get_account());\r\n\r\n$save_row&#x5B;'id']\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0= '&lt;root&gt;&lt;row id=&quot;'.$_main_data-&gt;get_id().'&quot;\/&gt;&lt;\/root&gt;';\r\n$save_row&#x5B;'log_update_by']\u00a0\u00a0 \u00a0= $access_obj-&gt;get_id();\r\n$save_row&#x5B;'log_update_ip'] \u00a0\u00a0 \u00a0= $access_obj-&gt;get_ip();\r\n$save_row&#x5B;'account'] \u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0= $_main_data-&gt;get_account();\r\n$save_row&#x5B;'department']\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0= $_main_data-&gt;get_department();\r\n$save_row&#x5B;'name_f'] \u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0= $account_lookup-&gt;get_account_data()-&gt;get_name_f();\r\n$save_row&#x5B;'name_l'] \u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0= $account_lookup-&gt;get_account_data()-&gt;get_name_l();\r\n$save_row&#x5B;'name_m'] \u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0= $account_lookup-&gt;get_account_data()-&gt;get_name_m();\u00a0\u00a0 \u00a0\r\n$save_row&#x5B;'sub_role_xml'] \u00a0\u00a0 \u00a0= $_obj_data_sub_request-&gt;xml();\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\r\n$sql_str = '{call account_update(@';\r\n$sql_str .= implode(' = ?, @', array_keys($save_row));\r\n$sql_str .= ')}';\r\necho $sql_str;\r\n\r\n\/\/\r\n<\/pre>\n<p>Obviously this alone won&#8217;t be enough, but the resulting output looks quite promising:<\/p>\n<blockquote><p>{call account_update(@id = ?, @log_update_by = ?, @log_update_ip = ?, @account = ?, @department = ?, @name_f = ?, @name_l = ?, @name_m = ?, @sub_role_xml)}<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<p>&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_post_was_ever_published":false,"_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}},"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":7,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/6417\/revisions"}],"predecessor-version":[{"id":6424,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/6417\/revisions\/6424"}],"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}]}}