^ Initial Steps

project-folder               structure and location of XML manifest
  | ....
  |- 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 contents of the ".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 the 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>

The rules are:

  1. if the detected type is listed under 'detected', the matching 'target' is rendered
  2. if it is not, 'default' is rendered
  3. if 'default' is empty, the detected type is rendered as-is.

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

If you need stronger typing in the generated DAO classes, read this: misc.html#strong-typing.

There may be some nuances depending on database/driver.

Example 1. The MySQL JDBC driver detects all field types correctly. At the same time, MySQL drivers for Go fetch all values as []uint8, so you may need to extend the type-map accordingly.

Example 2. The Oracle JDBC driver detects all numerics as "java.math.BigDecimal". At the same time, Go + "github.com/godror/godror" fetches all numerics as strings, so you may need to extend the type-map accordingly.

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. The JDBC driver for SQLite3 detects date/time as "java.lang.String" or "java.lang.Object", while Go + "github.com/mattn/go-sqlite3" fetches date/time as "time:time.Time".
In such cases, 'type-map' may not work, 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 the ones in the 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 <macros> section of "settings.xml" and reference those macros from "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 the plug-in GUI => tab "Admin" => [X] and in the 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"/>

^ Separation of Concerns

The generated code never touches your database API directly — no PDO, no JDBC, no QtSql. Every such call lives in a hand-written Proxy class, and the generated code reaches it through a single interface: DataStore.

That one boundary is what keeps the generated code small, and what lets the same XML manifest produce working code in five languages. The generator emits calls to DataStore and nothing else — what sits behind it is yours to decide.

The example below shows how to organize this in Go:

For more examples, see the Demo Projects and the plug-in GUI, tab 'Admin'.

Underlying database API Databases
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