<?xml version="1.0" encoding="ASCII"?>
<forth xmlns="http://forth.org.ru/ForthML/">

<wordlist name="mysql-hidden">

<slot2> charset database user pass  hostname port host  xml-stylesheet </slot2>
<slot> nport conn errno res resn  row col </slot>
<prop name="last-err-txt"><ss/></prop>

<def name="(connect)" ds=" -- ior ">
  CLIENT_MULTI_STATEMENTS
  0 <rem> unix_socket </rem>
  nport
  database  DROP
  pass      DROP
  user      DROP
  hostname  DROP
  conn
  mysql_real_connect
</def>

<def name="?conn" ds=" -- ">
  <choose>
    conn     0 EQ <when/>
    errno 2003 EQ <when/>
    <exit/>
  </choose>
  `#mysql-no-conn STHROW
</def>

<def name="(close-conn)" ds=" -- ">
  conn <if> conn mysql_close DROP 0 conn! </if>
</def>

<def name="treat-err" ds=" -- ">
  conn mysql_errno DUP errno! <unless><exit/></unless>
  errno 2006 = <if><rem> MySQL server has gone away </rem> (connect) DROP `#mysql-gone-away STHROW </if>
  conn mysql_error ASCIIZ> set-last-err-txt
  errno 2003 = <if><rem>Can't connect to MySQL server</rem>
    (close-conn) <rem> it can't reuse the connection object in this case </rem>
  </if>
  last-err-txt STHROW
</def>

<def name="set-conn-options" ds=" -- ">
  charset DUP <unless> 2DROP `utf8 </unless>
  DROP  MYSQL_SET_CHARSET_NAME  conn  mysql_options <unless> treat-err </unless>

  1 SP@ MYSQL_OPT_RECONNECT conn  mysql_options <unless> treat-err </unless>
  DROP  <!-- does't work before 5.1.6 -->
</def>

<include href="mysql.immutable.f.xml"/>

<export>

<def name="open" ds=" -- ">
  conn <unless> mysql_new_conn conn! set-conn-options </unless>
  (connect) <if><exit/></if>
  treat-err
</def>

<def name="close" ds=" -- ">
  0  errno!  0. set-last-err-txt
  conn <unless><exit/></unless>
  free-res-all (close-conn)
</def>

<handler event="shutdown"> close </handler>

<alias name="connect" word="open" />


<def name="assume-cred" ds=" d-db d-host d-user d-passw -- ">
  pass! user! hostname! database!
</def>

<def name="query-value" ds=" d-query -- d-value | 0 0 ">
  query  next-result? <if> next-row? <if> next-col? <if> get-value <exit/></if></if></if>
  0.
</def>

<def name="query-2value" ds=" d-query -- d-value1 d-value2 | 0 0  0 0 ">
  query-value
  res <if> row <if> next-col? <if> get-value <exit/></if></if></if>
  0.
</def>

</export>

<include href="enum-response.f.xml"/>


<wordlist name="buf">
  <include href="http://forth.org.ru/~pinka/model/io/stream-mem.L1.f.xml"/>
<comment> Generally speaking, it is not necessary.
          We can just save the consumer-xt and don't use the intermediate buffering.
</comment>
</wordlist>

<def name="store-chunk" ds=" addr u -- ">
  buf::write
</def>

<include href="serialize-xml.f.xml"/>


<def name="store-xml-stylesheet" ds=" -- ">
  xml-stylesheet NIP <unless><exit/></unless>
  <text><![CDATA[<?xml-stylesheet type="text/xsl" href="]]></text> store-chunk
  xml-stylesheet store-chunk
  <text><![CDATA["?>]]>&#xA;</text> store-chunk
  0. xml-stylesheet!
</def>

<export>

<def name="set-xml-stylesheet" ds=" d-url -- ">
  <comment> It should be set on each query </comment>
  xml-stylesheet! 
</def>

<def name="query-xml-per" ds=" d-query xt -- ">
  buf::clear
  <text><![CDATA[<?xml version="1.0"?>]]>&#xA;</text> store-chunk
  store-xml-stylesheet
  >R query store-response
  <repeat> buf::next-chunk DUP <while/> R@ EXECUTE </repeat> R> EXECUTE
</def>

</export>
</wordlist>
</forth>
