^ Initial Steps

project-folder               structure and location of XML meta-program
  | ....
  |- sdm                     SDM folder (any path, any name)
      |--- go.dal            root-file: an empty file named as 'php.dal', 'java.dal', 'cpp.dal', 'python.dal', or 'go.dal' (ensure lower case)
      |--- sdm.xml           declarations of DTO/model and/or DAO classes
      |--- settings.xml      common settings
      |--- sdm.xsd           ------ XSD-files for XML code completion and parsing
      |--- settings.xsd      ------
      |--- dao.xsd           ------
      |--- ProjectsDao.xml   external XML files as an option to declare DAO classes
  | ...
  | - .sdm                   config file of SDM sidebar tool-button (JetBrains only, none in Eclipse)

  1. Create/Open an SDM folder
  2. Create/Open (double-click) a root-file to enter the Plug-in GUI, switch to "Admin"
  3. Create XSD files, "sdm.xml", and "settings.xml"
  4. Click "settings.xml" to start editing. Read and follow the notes in XML comments. Save the changes.
  5. One of the buttons marked as [x] may be a good starting point. See also the Demo Projects

The content of ".sdm" file:

# more than one "*.dal" file in the same project is ok

sdm/go.dal              # path-name of the root-file from example above

sdm/sdm.xml             # add more files from SDM folder for quick access
sdm/settings.xml

src/my_favorite.php     # the others are ok as well

^ settings.xml -> examples of JDBC settings

JDBC Driver XML tag in 'settings.xml'
MySQL <jdbc jar="lib/mysql-connector-java-8.0.13.jar" class="com.mysql.cj.jdbc.Driver" url="jdbc:mysql://localhost/sakila" user="root" pwd="root"/>
Oracle <jdbc jar="lib/ojdbc8.jar" class="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@localhost:1521:orcl" user="ORDERS" pwd="sa"/>
PostgreSQL <jdbc jar="postgresql-42.2.9.jar" class="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/orders" user="postgres" pwd="sa"/>
SQL Server <jdbc jar="mssql-jdbc-8.2.2.jre11.jar" class="com.microsoft.sqlserver.jdbc.SQLServerDriver" url="jdbc:sqlserver://localhost\SQLEXPRESS;databaseName=AdventureWorks2014" user="sa" pwd="root"/>
xerial / sqlite-jdbc <jdbc jar="sqlite-jdbc-3.40.0.0.jar" class="org.sqlite.JDBC" url="jdbc:sqlite:$PROJECT_DIR$/northwindEF.sqlite" user="" pwd=""/>
H2 <jdbc jar="h2-1.4.190.jar" class="org.h2.Driver" url="jdbc:h2:$PROJECT_DIR$/h2_orders" user="" pwd="" />

^ settings.xml -> type-map

Here you specify how the types detected by code generator are rendered in the target code.

<type-map default="">
    <type detected="java.lang.Integer" target="int64">
    <type detected="java.lang.Double" target="float64">
    <type detected="java.lang.Float" target="float64">
    <type detected="java.lang.String" target="string">
    <type detected="byte[]" target="[]byte"/>
    <type detected="java.lang.Object" target="interface{}"/>
</type-map>

Algorithm of processing is the following:

  1. if detected type is found among 'detected', then related 'target' is rendered
  2. if not, then 'default' is rendered
  3. if 'default' is empty, detected type is rendered as-is.

If you want to create "type-map" from zero, read this: misc.html#type-map.

if you need more strong typing in generated DAO classes, read this: misc.html#strong-typing.

There may be some nuances depending on database/driver.

Example 1. MySQL JDBC driver detects all field types correctly. At the same time, MySQL divers for Go fetch all values as []uint8:

Example 2. Oracle JDBC driver detects all numerics as "java.math.BigDecimal". At the same time, Go + "github.com/godror/godror" fetches all numerics as strings:

Example 3. For Java + Android + SQLite, you may need this:

<type-map default="">
    <!-- On Dev. PC, it is Integer, but in Android run-time it is Long -->
    <type detected="java.lang.Integer" target="java.lang.Long"/>
</type-map>

Example 4. JDBC driver for SQLite3 detects date/time as "java.lang.String" or "java.lang.Object", but it happens that Go + "github.com/mattn/go-sqlite3" fetches date/time as "time:time.Time".
In such cases, 'type-map' may be not working, and you need explicit declarations:

<dto-class name="Orders" ref="get_orders.sql">
    <field type="time:time.Time" column="o_date"/>
</dto-class>

^ settings.xml -> macros

To generate complex fields like in example below

class Task(Base):
    __tablename__ = 'tasks'

    t_id = Column('t_id', Integer, primary_key=True, autoincrement=True)
    g_id = Column('g_id', Integer, ForeignKey('groups.g_id'))
    t_priority = Column('t_priority', Integer)
    t_date = Column('t_date', String(65535))
    t_subject = Column('t_subject', String(65535))
    t_comments = Column('t_comments', String(65535))

you will need to extend the section "settings.xml" => <macros> and use related references in "settings.xml" => <type-map><type ... target="...:

<type-map default="">
    <type detected="sa-java.lang.Integer" target="${sa-type}|0:Integer"/>
    <type detected="sa-java.lang.Float" target="${sa-type}|0:Float"/>
    <type detected="sa-java.lang.String" target="${sa-type}|0:String"/>
    <type detected="sa-byte[]" target="${sa-type}|0:LargeBinary"/>
    <type detected="sa-java.lang.Object" target="${sa-type-unknown}"/>
type-map>
<macros>
    <macro name="${sa-type-unknown}" value="${sa-column-base}|type:"/>

    <macro name="${sa-type}" value="${sa-column-base}|type:, ${0}"/>

    <macro name="${sa-column-base}"/>
            <vm/>
                <![CDATA[= Column('${column}'${type}#if($fi.ColumnSize>0)($fi.ColumnSize)#end#if($fi.FK), ForeignKey('$fi.FK')#end
#if($fi.PK), primary_key=True#end
#if($fi.AI), autoincrement=True#end
#if(!$fi.PK)
#if($fi.Indexed), index=True#end
#if($fi.Unique), unique=True#end
#if($fi.Nullable), nullable=True#end
#end)${comment}]]/>
            </vm/>
    </macro/>
macros>

Examples of the field-related macros are available in plug-in GUI => tab "Admin" => [X] and in Demo-Projects: https://github.com/panedrone/sqldalmaker

To customize class-based macros, use this:

  • refs to entries of section <macros>:

    <dto scope="" inheritance="" field-names-mode="0" macro="${dto}"/>
    <dao scope="" field-assign-mode="0" macro="${dao}"/>
  • refs to external files:

    <dto scope="" inheritance="" field-names-mode="0" macro="sdm/python.models.vm"/>
    <dao scope="" field-assign-mode="0" macro="sdm/python.dao.vm"/>

^ Areas of Responsibility

  • Generated Code is free of direct calls to an underlying DB-accessing API (PDO, JDBC, QtSql, etc.)
  • All low level stuff is wrapped into a Proxy class
  • Meaningful functionality of Proxy class it exposed with an interface DataStore
  • Generated Code is based on DataStore which makes it is minimalistic and well readable.

Example below is to demonstrate how to organize it in Golang:

For more examples, refer Demo-Projects and the plugin GUI, tab 'Admin'.

Underlying DB-accessing API Comments
PHP MySQL, Oracle, PostgreSQL, SQL Server, SQLite3
Java Available through JDBC:
MySQL, Oracle, PostgreSQL, SQL Server, SQLite3, H2, HSQLDB, Derby, IBM DB2, IBM Informix, Firebird, etc.
C++ Databases supported by Qt: http://doc.qt.io/qt-5/sql-driver.html
Python -
Go Tested with MySQL, Oracle, PostgreSQL, SQL Server, and SQLite3.

^ Top