'' ,'password'=>'' #,'filename'=>null // synonym for database ,'database'=>'' ,'dbhost'=>'' // used for mysql #,'dbopts'=>null #,'dsn'=>null ,'engine'=>'' ,'FS'=>'' ,'OFS'=>',' ,'IFS'=>',' ,'RS'=>'' ,'IRS'=>"\n" #,'ors'=>null // synonym for 'newline' ,'newline'=>"\n" ,'default_section'=>'#defaults' ,'enclosure'=>'"' ,'escape'=>'\\' ,'sql'=>'' #,'table'=>null #,'itable'=>null #,'otable'=>null #,'csv'=>null #,'icsv'=>null #,'ocsv'=>null )); # $pagename is our current page (usually where the script resides) # $DBDefPage is contains the page (&, optionally, section) where the SQL # definitions reside # $opts will pass back the defined options: # ['sql'] = 'the actual statement(s) to be executed' # ['username'] # ['password'] # ['database'] # ['engine'] # ['OFS'] (output field separator) # ['IFS'] (input field separator) # ['IRS'] (input record separator) function wshdbInitialize($pagename, $DBDefPage, &$opts) { global $WikiShDb, $wshAuthPage, $wshdbEnableDBConfigOnPage; $func="wshdbInitialize"; wdbg(4,"$func($pagename, $DBDefPage): Entering"); ## # Options ($WikiShDb (lowest), #defaults, $DBDefPage, $opts (highest)) ## $pn = MakePageName($pagename, $DBDefPage); // strip #section $section = str_replace($pn, '', $DBDefPage); if (wshIsAWikiPage(false, $pn)) { $pna = substr($pn, strlen(WIKIPAGEID)); $pnb = substr($DBDefPage, strlen(WIKIPAGEID)); } else { $pna = $pn; $pnb = $DBDefPage; } if (!slAuthorized($pna, $wshAuthPage, 'SQL') && !slAuthorized($pnb, $wshAuthPage, 'SQL')) { wshStdErr($pagename, $opts, "ERROR: Page \"$pagename\" does not have SQL privileges on \"$pna\" or \"$pnb\""); return false; } #echo "DEBUG: DBDefPage=$DBDefPage, pn=$pn
\n"; if (!($page = wshReadPage($pagename, $opts, $pn)) || !@$page['text']) { wshStdErr($pagename, $opts, "ERROR: Non-existent (or blank) page \"$pn\""); return false; } #echo "DEBUG: page[text]=
$page[text]

\n"; #echo "DEBUG: page=
".print_r($page,true)."

\n"; #echo "DEBUG: WikiShDb=
".print_r($WikiShDb,true)."

\n"; $WikiShDb = wshdbOptSynonyms($pagename, $WikiShDb, true); if ($dflt_text = TextSection($page['text'], $WikiShDb['default_section'])) { #echo "DEBUG: dflt_text=$dflt_text
\n"; $dflt_text = preg_replace("/#.*$/", '', $dflt_text); // strip comments $defaults = wshdbOptSynonyms($pagename, ParseArgs($dflt_text), $wshdbEnableDBConfigOnPage); #echo "DEBUG: text of defaults=$dflt_text, parsed=
".print_r($defaults,true)."

\n"; } else { #echo "DEBUG: No #default section
\n"; $defaults = array(); } if ($opts['sql']) $dbdef_opts = array(); else { if (!($text = TextSection($page['text'], $section))) { wshStdErr($pagename, $opts, "ERROR: Non-existent section \"$section\" in page \"$pn\""); return false; } $text = preg_replace("/#.*$/", '', $text); // strip comments list($opt_text, $sql_statement) = preg_split("/^\s*[-=]{4,}\s*$/m", $text); if (!$sql_statement) { // no divider - means no opts were specified $sql_statement = $text; $opt_text = ''; } #echo "DEBUG: opt_text=$opt_text, sql_statement=$sql_statement
\n"; $dbdef_opts = wshdbOptSynonyms($pagename, ParseArgs($opt_text), $wshdbEnableDBConfigOnPage); $opts['sql'] = trim($sql_statement); } #echo "DEBUG: text of $section=$text, parsed=
".print_r($dbdef_opts,true)."

\n"; $opts = wshdbOptSynonyms($pagename, $opts, $wshdbEnableDBConfigOnPage); #echo "DEBUG: opts=".print_r($opts,true)."
\n"; #echo "DEBUG: dbdef_opts=".print_r($dbdef_opts,true)."
\n"; #echo "DEBUG: defaults=".print_r($defaults,true)."
\n"; #echo "DEBUG: WikiShDb=".print_r($WikiShDb,true)."
\n"; $opts = array_merge($WikiShDb, $defaults, $dbdef_opts, $opts); #echo "DEBUG: AFTER opts=".print_r($opts,true)."
\n"; if (!@$opts['dsn']) { switch ($opts['engine']) { case 'mysql': if (!$opts['database']) wshStdErr($pagename, $opts, "ERROR: MySQL database not specified in database"); if (!$opts['database']) wshStdErr($pagename, $opts, "ERROR: MySQL host not specified in dbhost"); $opts['dsn'] = "mysql:dbname=$opts[database];host=$opts[dbhost]"; break; case 'sqlite': default: if (!$opts['database']) { if (@$opts['engine']) wshStdErr($pagename, $opts, "ERROR: SQLite file not specified in database ($opts[engine])"); else wshStdErr($pagename, $opts, "ERROR: Database engine not configured"); return false; } $opts['dsn'] = "sqlite:$opts[database]"; break; } } wdbg(3,"$func: dsn=$opts[dsn]"); ## # Now open the database ## try { # Note that $opts['dbopts'] can be set only via config.php when # you set up $WikiShDb['dbopts']. $dbh = new PDO($opts['dsn'], $opts['username'], $opts['password'], $opts['dbopts']); } catch (PDOException $e) { wshStdErr($pagename, $opts, "ERROR: Connection failed: " . $e->getMessage() . "
(Error occurred while attempting to open dsn=$opts[dsn])"); return false; } $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $opts['dbh'] = $dbh; return true; } # This function takes certain meta-options (--csv, --table, etc.) and # "fills them out" to say what the --IFS or --IRS options should be. function wshdbOptSynonyms($pagename, $opts, $leave_db_config=true) { if (!$leave_db_config) { #echo "BEFORE: opts=
".print_r($opts,true)."

\n"; $opts = array_diff_key($opts, array('database'=>0, 'dbhost'=>0, 'dsn'=>0, 'username'=>0, 'password'=>0, 'engine'=>0, 'filename'=>0, 'dbopts'=>0)); #echo "AFTER: opts=
".print_r($opts,true)."

\n"; } unset($opts['']); // unused unset($opts['#']); // unused if ($opts['ors']) { SDV($opts['newline'], $opts['ors']); unset($opts['ors']); } if (@$opts['csv']) { SDVA($opts, array( 'icsv'=>true, 'ocsv'=>true )); #unset($opts['csv']); // don't unset this - we check for it later } if (@$opts['ocsv']) { SDVA($opts, array( 'OFS'=>',', 'line_prefix'=>'', 'line_suffix'=>'', 'newline'=>"\n" )); #unset($opts['ocsv']); // don't unset this - we check for it later } if (@$opts['icsv']) { SDVA($opts, array( 'IFS'=>',', 'line_prefix'=>'', 'line_suffix'=>'', 'IRS'=>"\n" )); #unset($opts['icsv']); // don't unset this - we check for it later } if (@$opts['table']) { $opts['itable'] = true; $opts['otable'] = true; unset($opts['table']); } if (@$opts['itable']) { SDVA($opts, array( 'IFS'=>'/\|\|/', 'line_prefix'=>'||', 'line_suffix'=>'||', 'IRS'=>"\n" )); unset($opts['itable']); } if (@$opts['otable']) { SDVA($opts, array( 'OFS'=>'||', 'line_prefix'=>'||', 'line_suffix'=>'||', 'newline'=>"\n" )); unset($opts['otable']); } if ($opts['FS']) { SDV($opts['IFS'], $opts['FS']); SDV($opts['OFS'], $opts['FS']); unset($opts['FS']); } if ($opts['RS']) { SDV($opts['IRS'], $opts['RS']); SDV($opts['newline'], $opts['RS']); unset($opts['RS']); } if ($opts['filename']) { SDV($opts['database'], $opts['filename']); unset($opts['filename']); } if ($opts['read0']) { SDVA($opts, array( 'IFS'=>CHR(1), 'IRS'=>CHR(2), 'line_prefix'=>'', 'line_suffix'=>'' )); unset($opts['read0']); } if ($opts['print0']) { SDVA($opts, array( 'OFS'=>CHR(1), 'newline'=>CHR(2), 'line_prefix'=>'', 'line_suffix'=>'' )); unset($opts['print0']); } foreach (array('IFS', 'OFS', 'IRS', 'newline', 'line_prefix', 'line_suffix') as $i) if (isset($opts[$i])) $opts[$i] = str_replace('\n', "\n", $opts[$i]); #echo "DEBUG: returning opts=".print_r($opts,true)."
\n"; return $opts; } # # Allow SELECT statements via Markup Expressions # $MarkupExpr["SQLselect"] = 'wshdbSQLexec($pagename, "select", @$argp, @$args)'; # # Allow INSERT/UPDATE statements via Markup Expressions # (also COMMIT, etc.) # $MarkupExpr["SQLdelete"] = 'wshdbSQLexec($pagename, "exec", @$argp, @$args)'; $MarkupExpr["SQLupdate"] = 'wshdbSQLexec($pagename, "exec", @$argp, @$args)'; $MarkupExpr["SQLinsert"] = 'wshdbSQLexec($pagename, "exec", @$argp, @$args)'; $MarkupExpr["SQLexec"] = 'wshdbSQLexec($pagename, "exec", @$argp, @$args)'; function wshdbSQLexec($pagename, $mode, $opts, $args) { global $WikiShVars, $WikiShPipeActive, $WikiShPipeText; if (wshNotNow($pagename)) return(''); $func="SQLexec()"; wdbg(4,"$func: Entering"); wdbg(1,$args); wshInitOpts($pagename, '', $opts, $args, true, false); // don't process pipe - we handle that manually below #echo "DEBUG: args=
".print_r($args,true)."

\n"; if (@$opts['sql']) { // SQL statement was specified in-line, must have SQL auth on current pg $SQL_defs = array($pagename); // will only be used for authorization now } else { $SQL_defs = array(array_shift($args)); // 1st arg contains SQL def } wdbg(3, "$func: SQL_defs=".print_r($SQL_defs,true)); wshExpandWildCards($pagename, $opts, $SQL_defs, false, false, false); $SQL_def = array_shift($SQL_defs); wdbg(3,"$func: SQL_def=$SQL_def"); if (wshdbInitialize($pagename, $SQL_def, $opts)) { #echo "DEBUG: final opts=
".print_r($opts,true)."

\n"; $dbh = $opts['dbh']; } else { wshStdErr($pagename, $opts, "ERROR: Cannot Initialize WikiShDb (see above)"); $WikiShVars['STATUS'] = 1; return false; } wdbg(3,"$func: SQL=$opts[sql]"); try { $stmt = $dbh->prepare($opts['sql']); } catch (PDOException $e) { wshStdErr($pagename, $opts, "ERROR: Statement preparation failed: " . $e->getMessage() . "
(Error occurred while attempting to prepare sql=$opts[sql])"); $stmt = false; } if ($stmt === false) { wshStdErr($pagename, $opts, "ERROR: Invalid SQL ($opts[sql])"); $WikiShVars['STATUS'] = 1; return false; } $macros = array(); foreach (preg_grep("/^_/", array_keys($opts)) as $k) // named params $macros[':'.substr($k,1)] = $opts[$k]; if (!$macros) $macros = $args; // positional params if ($macros) { $macros = array($macros); // convert to array of array for below } else { // OK, try looking for stdin (either from pipe or redirected) if ($WikiShPipeActive) { $text = $WikiShPipeText; $WikiShPipeActive = $WikiShPipeText = false; // get rid of pipe } elseif ($opts['stdin']) { if (!wshIsAWikiPage('', $opts['stdin']) && !wshIsATextFile('', $opts['stdin']) && !wshIsASessionFile('', $opts['stdin']) && !wshIsASessionGroup($opts['stdin'])) $opts['stdin'] = WIKIPAGEID . $opts['stdin']; $page = wshReadPage($pagename, $opts, $opts['stdin']); $text = $page['text']; } // OK, we've got text - now split it up... #echo "DEBUG: Checking for CSV
\n"; if ($opts['csv'] || $opts['icsv']) { #echo "DEBUG: Found CSV
\n"; #echo "DEBUG: CSV text=
$text

\n"; $macros = parse_csv($text, $opts); #echo "DEBUG: CSV rows=
".print_r($macros,true)."

\n"; } else { $rows = array(); #echo "DEBUG: SQLexec(): IRS=$opts[IRS], IFS=$opts[IFS]
\n"; if ($opts['IRS']{0} == '/') $tmprows = preg_split($opts['IRS'], $text); else $tmprows = explode($opts['IRS'], $text); foreach ($tmprows as $row) if (trim($row)) { if ($opts['IFS']{0} == '/') $rows[] = preg_split($opts['IFS'], $row); else $rows[] = explode($opts['IFS'], $row); } $macros = $rows; } } if (!$macros) { // OK, just run it once - must not be any parms $macros = array(array()); } $rtn = true; $count = 0; $out = array(); #echo "DEBUG: sql=$opts[sql], macros=
".print_r($macros,true)."

\n"; wdbg(3,"$func: looping with macros=".print_r($macros,true)); foreach ($macros as $macro) { wdbg(3,"$func: macro=".print_r($macro,true)); try { $rtn = $stmt->execute($macro); } catch (PDOException $e) { wshStdErr($pagename, $opts, "ERROR: Statement execution failed: " . $e->getMessage() . "
(Error occurred while attempting to execute sql=$opts[sql], macro=".print_r($macro,true).")
\n"); $rtn = false; } if ($rtn === false) { break; } if ($mode == 'select') { $stmt->setFetchMode(PDO::FETCH_ASSOC); $Results = $stmt->fetchAll(); foreach ($Results as $row){ if (!$row) continue; // PDO returns FALSE if no results #echo "DEBUG: $func: row=".print_r( $row,true)."
\n"; wdbg(2,"$func: OFS=$opts[OFS], newline=".wshDbgOd($opts[newline]).", row=".print_r( $row,true)); $out[] = csv_implode($opts, $row); $count++; } $page = array('filename'=>''); // junk for calls to wshReplace() if ($opts['file_prefix']) $array_prefix = array(wshReplace($opts, $page, $opts['file_prefix'])); else $array_prefix = array(); $line_prefix = wshReplace($opts, $page, $opts['line_prefix']); $line_suffix = wshReplace($opts, $page, $opts['line_suffix']); if ($line_prefix || $line_suffix) for ($i = 0; $i < sizeof($out); $i++) { if (strstr($opts['line_prefix'], 'LINENO')) $line_prefix = wshReplace($opts, $page, $opts['line_prefix'], $i+1); $out[$i] = $line_prefix . $out[$i] . $line_suffix; } $out = array_merge($array_prefix, $out); } else { $count += $stmt->rowCount(); } } if ($rtn !== false) { $WikiShVars['STATUS'] = 0; $WikiShVars['SQL_COUNT'] = $count; $WikiShVars['SQL_PLURAL'] = ($count == 1 ? '' : 's'); // simplistic but helpful } else { $WikiShVars['STATUS'] = 2; $WikiShVars['SQL_COUNT'] = 0; $WikiShVars['SQL_PLURAL'] = 's'; } return (wshPostProcess($pagename, $opts, $out, $page)); } # csv_implode() will handle basic CSV output, etc. # It respects # $opts['OFS'] (output field separator, usually comma) # $opts['enclosure'] (usually double-quotes) # $opts['newline'] (usually "\n") # $opts['escape'] (usually backslash) # $opts['csv'] or $opts['ocsv'] - must be set to actually do csv output function csv_implode($opts, $fields) { #echo "csv_implode: entering
\n"; if ($opts['csv'] || $opts['ocsv']) { #echo "csv_implode: in CSV
\n"; $rtn = ''; foreach ($fields as $f) { #echo "csv_implode: f=$f
\n"; if ($rtn) $rtn .= $opts['OFS']; $need_enclosure = false; foreach (array($opts['OFS'], $opts['enclosure'], $opts['newline'], $opts['escape']) as $char) { if ($char && (strpos($f, $char) !== false)) { $need_enclosure = true; break; } } if ($need_enclosure) { $rtn .= $opts['enclosure'].str_replace($opts['enclosure'], $opts['escape'].$opts['enclosure'], $f).$opts['enclosure']; } else { $rtn .= $f; } } } else { $rtn = implode($opts['OFS'], $fields); } #echo "csv_implode: returning \"$rtn\"
\n"; return $rtn; } # parse_csv() # take a string ($str) and return a 2-dimensional array, rows of cols function parse_csv($str, $opts) { SDV($opts['len'], 4096); #echo "DEBUG: parse_csv: opts=
".print_r($opts,true)."

\n"; #echo "DEBUG: parse_csv: str=
$str

\n"; $fh = fopen('php://memory', 'rw'); fwrite($fh, $str); rewind($fh); $results=array(); while ($oneline = fgetcsv( $fh, $opts['len'], $opts['IFS'], $opts['enclosure'], $opts['escape'])) { #echo "DEBUG: oneline=
".print_r($oneline,true)."

\n"; #echo "DEBUG: oneline[0]=".wshDbgOd($oneline[0])."
\n"; if ($oneline && $oneline !== array(null)) $results[] = $oneline; } fclose($fh); return $results; }