Skip to content
This repository has been archived by the owner on Jul 31, 2020. It is now read-only.

yupswing/aspdbox

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ASPdBox

ASPdBox è un insieme di classi per ASP3 che si occupano di interfacciarsi fra la vostra applicazione e il database (sono supportati MDB e MYSQL) senza farvi preoccupare troppo di quale database stiate effettivamente utilizzando; inoltre vi offre una serie di utilità atte a semplificare la creazione di query sql sia per l'input che per l'output.

Attualmente esistono due classi:
ASPdBManager si occupa di gestire la connessione con il database, di fornirvi tutti i metodi utili alla creazione di query compatibili, metodi per il controllo dei dati e soprattutto una serie di potenti metodi per la modifica della struttura del database.
ASPdBPagination si occupa di rendere "ridicola" l'esecuzione di una paginazione, proprio come se steste facendo una normalissima query; oltre a ciò vi chiede quanti record per pagina e che pagina visualizzare, il resto lo fa lei e vi restituisce un recordset statico (sola lettura) pronto per essere "stampato"

(Per vedere esempi pratici potete guardare i file DEMO presenti nel repository)


Classe ASPdBManager

Tutto ciò che bisogna sapere su questa classe è che prima di fare qualsiasi cosa (dopo ovviamente averla istanziata) è impostare un database (se non si imposta obj.database verrà considerato "mdb") e successivamente aprire una connessione, poi automaticamente tutti i metodi diventano disponibili e funzionanti, senza dimenticarsi di disconnettersi alla fine del lavoro/pagina

Instanza minimale:

dim obj
set obj = Class_ASPdbManager
obj.database = "mdb" 'oppure "mysql", mi raccomando MINUSCOLO
obj.debugging = true 'false è di default, se fate prove lasciatelo a TRUE, conviene
'pronti per i metodi

Vediamo ora di analizzare i metodi che mette a disposizione la classe

Connect(db,user,password,options)
Niente di complesso da spiegare. Senza questa operazione tutti gli altri metodi genereranno errori gestiti (nessuna connessione attiva) e quindi risulteranno inutilizzabili.
Nel caso mdb sarà necessario indicare un percorso DB (il metodo si occupa di fare il Server.MapPath) esistente, una password (se necessario). La stringa base di connessione è la seguente "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = " & server.MapPath(db) & "; Persist Security Info = False;" & options
Nel caso mysql sarà necessario indicare un nome DB, un utente e una password (se necessario). La stringa base di connessione è la seguente "db=" & db & "; driver=MySQL ODBC 3.51 Driver; uid=" & user & "; pwd=" & password & ";" & options (nelle options può venire utile indicare "Server=[host]" se mysql lo richiede)
restituisce FALSE se la connessione non va a buon fine

Disconnect()
Chiude la connessione e distrugge gli oggetti utilizzati.


metodi di modifica

CreateNew(db,user,password,options,overwrite)
Crea un nuovo database (da effettuarsi PRIMA di un Connect).
Nel caso mdb è necessario indicare un percorso DB (il metodo si occupa di fare il Server.MapPath) [user, password e options non vengono utilizzati]
- Il metodo si occupa di creare un nuovo MDB. Se esiste già restituisce FALSE, se overwrite = true elimina il file e ne crea uno nuovo vuoto e restituisce TRUE.
Nel caso mysql è necessario indicare un DB esistente (!), e i valori user, password e options necessari per connettervisi (come Connect).
- Il metodo si occupa di verificare che il database sia vuoto ed esista. Se non lo è restituisce FALSE, se overwrite = true distrugge tutte le tabelle presenti e restituisce TRUE. [attualmente il metodo NON può creare un nuovo database mysql]
Quindi in entrambi i casi PRUDENZA con overwrite = true.

CreateTable(tablename,columnid,tableoptions,skipifexist)
Crea una nuova tabella.
tablename è il nome della nuova tabella, columnid è il nome del campo che vi verrà generato all'interno (sarà un campo di tipo CONTATORE).
tableoptions è una stringa che verrà aggiunta al termine della SQL (per mysql se lasciato vuoto o null il valore assume "TYPE=INNODB CHARSET=UTF8")
skipifexist: se TRUE e la tabella già esiste restituisce TRUE senza fare nulla, se FALSE e la tabella esiste la elimina e ne crea una nuova e restituisce TRUE
restituisce FALSE se la creazione della tabella non va a buon fine

DropTable(tablename)
Elimina una tabella (viene effettivamente eseguito SOLO se la tabella esiste)
restituisce FALSE se la eliminazione della tabella non va a buon fine

AddColumn(tablename,columnname,columnoptions,fill,skipifexist)
Crea un campo in una tabella.
tablename è il nome della tabella, così come columnname è il nome del nuovo campo.
le columnoptions sono OPTIONS (vedi appendice).
fill è il valore che deve essere impostato sul campo per i record già esistenti (il valore non viene controllato, assicurarsi di indicarlo correttamente, si consiglia l'utilizzo delle funzioni di formattazione)
skipifexist: se TRUE e il campo già esiste restituisce TRUE senza fare nulla, se FALSE e il campo esiste la elimina e ne crea uno nuovo e restituisce TRUE
restituisce FALSE se la creazione del campo non va a buon fine

ModifyColumn(tablename,columnname,columnoptions,adapt)
Modifica la struttura di un campo in una tabella.
tablename è il nome della tabella, così come columnname è il nome del nuovo campo.
le columnoptions sono OPTIONS (vedi appendice).
se adapt = TRUE prima di eseguire la modifica fa un Left (se il campo è testuale) per evitare errori di troncamento
restituisce FALSE se la modifica del campo non va a buon fine

DropColumn(tablename,columnname)
Elimina un campo (viene effettivamente eseguito SOLO se il campo esiste)
restituisce FALSE se la eliminazione del campo non va a buon fine

AddIndex(tablename,columnname,indexoptions,skipifexist)
Crea un indice su un campo
tablename è il nome della tabella, così come columnname è il nome del campo.
le indexoptions sono OPTIONS (vedi appendice).
skipifexist: se TRUE e l'indice già esiste restituisce TRUE senza fare nulla, se FALSE e l'indice esiste la elimina e ne crea uno nuovo e restituisce TRUE
restituisce FALSE se la creazione dell'indice non va a buon fine

DropIndex(tablename,indexname)
Elimina un indice (viene effettivamente eseguito SOLO se l'indice esiste)
restituisce FALSE se la eliminazione dell'indice non va a buon fine

AddForeignKey(tablename,columnname,byval foreignkeyname,references,foreignkeyoptions,skipifexist)
Crea una relazione fra due (o più) campi
tablename è il nome della tabella, così come columnname è il nome del campo.
la foreignkeyname è il nome della relazione (se non impostato la chiama "FK_tablename_columnname")
references è il riferimento (es di valore accettato: "nometabella(nomecampo)")
le foreignkeyoptions sono OPTIONS (vedi appendice).
skipifexist: se TRUE e la foreign key già esiste restituisce TRUE senza fare nulla, se FALSE e la foreign key esiste la elimina e ne crea una nuova e restituisce TRUE
restituisce FALSE se la creazione della foreign key non va a buon fine

DropForeignKey(tablename,foreignkeyname)
Elimina una relazione (viene effettivamente eseguito SOLO se la relazione esiste)
restituisce FALSE se la eliminazione della relazione non va a buon fine


metodi di interrogazione

TableExists(tablename)
Resituisce TRUE/FALSE a seconda se la tabella indicata esista o meno

TablesOnDatabase()
Restituisce un array con i nomi di tutte le tabelle nel database
(se non vi sono tabelle restituisce un array con un elemento vuoto)
(in MDB non inserisce le tabelle di sistema "MSys*"

ColumnExists(tablename,columnname)
Resituisce TRUE/FALSE a seconda se la colonna indicata esista o meno

ColumnsOnTable(tablename)
Restituisce un array con i nomi di tutti i campi nella tabella
(se non vi sono tabelle restituisce un array con un elemento vuoto)

IndexExists(tablename,indexname)
Resituisce TRUE/FALSE a seconda se l'indice indicato esista o meno

IndexesOnTable(tablename)
Restituisce un array con i nomi di tutti gli indici nella tabella
(se non vi sono tabelle restituisce un array con un elemento vuoto)

ForeignKeyExists(tablename,foreignkeyname)
Resituisce TRUE/FALSE a seconda se la relazione indicata esista o meno

ForeignKeysOnTable(tablename)
Restituisce un array con i nomi di tutte le relazioni nella tabella
(se non vi sono tabelle restituisce un array con un elemento vuoto)


metodi di compatibilità/input/output

compatibleSQL(SQL)
Data una SQL ne restituisce una versione compatibile con il database in uso.
L'SQL se già corretta non verrà modificata
(attualmente applica modifiche SOLO alle istruzioni DELETE e LIMIT/TOP
verificare la compatibilità delle proprie query se esulano da questi due casi per il/i database utilizzati
se ci sono consigli da dare segnalate!)

fDate(date)
Data una data restituisce la stringa da inserire in SQL per il database in uso
es:

SQL = "UPDATE miatabella SET campodata = " & obj.fDate(now) & ";"
obj.conn.execute(SQL)

nel caso indicato aggiorna tutta la tabella impostando la data odierna.
notare che non sono stati inserite apici (') o altri simboli.
la funzione provvede a restituirli se necessario

fString(value)
Restituisce la stringa formattata per evitare errori/sql injection
es:

SQL = "UPDATE miatabella SET campotesto = '" & obj.fString("questo e' un test") & "';"
obj.conn.execute(SQL)

nel caso indicato aggiorna tutta la tabella impostando "questo e' un test".
notare che debbono essere indicati apici (') prima e dopo.
inoltre grazie a fString la presenza di un apici nel testo non presenterà errori

fNumber(value)
Restituisce la stringa formattata per evitare errori
es:

SQL = "UPDATE miatabella SET camponumerico = " & obj.fNumber("25,2") & ";"
obj.conn.execute(SQL)
SQL = "UPDATE miatabella SET camponumerico = " & obj.fNumber(clng(12)) & ";"
obj.conn.execute(SQL)

nel caso indicato aggiorna tutta la tabella impostando 25.2 o 12
notare che la funzione accetta sia valori effettivamente numerici che stringhe
si occuperà lei di modificarli secondo necessità.
inoltre, indicare stringhe non numeriche non presenterà errori, ma una restituzione di 0


Le opzioni, che sono?

Per semplificarci la vita, invece che mettere decine di argomenti molto spesso inutilizzati ho pensato di fare un'unica stringa in cui vengono scritti tutti i valori necessari.
La sintassi è: ":nome=valore,:altronome=altrovalore"
Le funzioni che utilizzano le OPZIONI sono AddColumn, ModifyColumn, AddIndex e AddForeignKey

AddColumn,ModifyColumn
le opzioni valide (a seconda dei casi) sono

  • :type tipologia di campo(vedi sotto per la tabella dei valori)
  • :size numero di caratteri (utilizzato per type = char o varchar)
  • :signed true/false [il numero è positivo o negativo] (utilizzato SOLO in mysql per i campi numerici)
  • :null true/false [il campo può essere null] (tutti i campi)
  • :default stringa/numero valore automatico (tutti i campi, se non dato e NOT NULL per i numerici è 0)
  • :binary true/false [campo binario] (utilizzato per type = char, varchar e memo)

AddIndex
le opzioni valide (a seconda dei casi) sono

  • :name nome dell'indice (se non dato utilizza il nome del campo)
  • :index
    • UNIQUE (mysql) (mdb)
    • FULLTEXT (mysql [myisam {char,varchar,text}])
    • SPATIAL (mysql [myisam {not null}])
  • :type
    • BTREE (mysql [myisam,innodb,memory])
    • HASH mysql [memory,ndb])
    • RTREE (mysql [myisam]) [solo per SPATIAL index]

AddForeignKey
le opzioni valide (a seconda dei casi) sono

  • :onupdate, :ondelete (solo mysql)
    • CASCADE delete or update the row from the parent table and automatically delete or update the matching rows in the child table
    • SET NULL delete or update the row from the parent table and set the foreign key column or columns in the child table to NULL.
    • NO ACTION reject delete or update actions on parent table
    • RESTRICT same as NO ACTION


Tabella dei tipi compatibili

Rappresenta la conversione dal valore indicato in :type a quello effettivamente utilizzato nelle query di creazione/modifica dei campi
Se vi sono errori o imperfezioni ogni consiglio è bene accetto, ho cercato di renderli più sinonimi possibile

:type mdb mysql
counter COUNTER UNIQUE NOT NULL PRIMARY KEY INT(10) AUTO_INCREMENT UNIQUE NOT NULL PRIMARY KEY
boolean BIT BOOLEAN
date DATETIME DATETIME
short SHORT SMALLINT
long LONG INT
single SINGLE FLOAT
double DOUBLE DOUBLE
currency CURRENCY DECIMAL(19,4)
char TEXT CHAR
varchar TEXT VARCHAR
memo LONGTEXT LONGTEXT
blob LONGBINARY LONGBLOB

Classe ASPdBPagination

E ora veniamo a questa piccola perla (si lo so sono megalomane): ASPdBPagination
E' una piccola classe che si occupa di fare la paginazione e risparmiarvi la noiosa implementazione "volta per volta". L'utilizzo è di una semplicità che definirei goduriosa (si sono molto soddisfatto)

Prima di tutto istanziamo la classe

<!--#include file = "includes/class.aspdbbox.asp"-->
<%
dim obj, database
'Conn è un oggetto Connection valido e in stato OPEN
database = "mysql" 'oppure "mdb"
set obj = new Class_ASPDbPagination
onj.RecordsPerPageDefault = 25 'si può impostare il valore base di record per pagina
obj.debugging = true 'come al solito il debuggin non è necessario, ma utile durante i test
%>

E poi?

<%
dim looper
if obj.Paginate(Conn, database, 5, null, _
"SELECT id, campoa FROM tabella ORDER BY id") then
    looper = 0
    while not obj.recordset.eof and (looper < obj.RecordsPerPage or database = "mysql")
        response.write "<strong>id</strong>:" & obj.recordset("id") & "<br/>" & _
        "<strong>campoa</strong>:" & obj.recordset("campoa") & "<br/>"
        obj.recordset.movenext
        looper = looper + 1
    wend
    obj.recordset.close
'* opzionale: stampa il box di navigazione (per maggiori personalizzazioni è possibile crearlo autonomamente)
response.write obj.printNavigator(null,null,null,false)

else 'errore nella query o nella classe (sob) 'attivare il debugging per verificare quale sia end if %>

In questo caso la query è semplice, ma non ci sono quasi limiti nella sua creazione, vediamo quali:
- la query deve essere funzionante [potete testarla dando come parametro RECORDSPERPAGE = 0]
- per l'utilizzo su entrambi i database mantenere la sintassi comune
- vietato l'utilizzo di LIMIT x,y (la classe serve proprio a questo)

Per il resto sono supportati l'utilizzo di:

  • tutta la sintassi base SQL (compatibile con MDB e/o MYSQL) [JOIN,GROUP BY,HAVING,SELECT DISTINCT,WHERE...etc.etc.]
  • UNION e UNION ALL
  • TOP x e LIMIT x (sia in query UNION che per singole select si può utilizzare TOP x e LIMIT x)
      nella stessa query sono permessi anche mescolamenti (una SELECT con TOP e una con LIMIT)
      l'applicazione si occupa di renderli compatibili per il database in uso
  • se utilizzato First(column) o Last(column) la query viene resa compatibile con MySQL, ma ovviamente se ne perdono le funzionalità


Vediamo i pochi metodi nel dettaglio:

Paginate(Conn, database, recordsPerPage, Page, pagsql)
Conn è una connessione attiva (se utilizzate ASPdBManager potete usare quella)
database è il tipo di database (valori validi "mdb","mysql")
recordPerPage è il numero di record per pagina (se impostata a NULL viene valorizzata tramite request.QueryString("perpage"); se da querystring viene passato un valore 0 o negativo viene utilizzato RecordsPerPageDefault)
  impostando il valore recordPerPage a 0 la paginazione non verrà effettuata e potrete verificare la bontà della query)
page è la pagina corrente (se impostata a NULL viene valorizzata tramite request.QueryString("page"))
pagsql è la query da paginare (vedi limitazioni indicate sopra)

i valori per page e recordperpage vengono validati prima di essere utilizzati
se la pagina è superiore al numero delle pagine viene impostata a 1

Paginate restituisce TRUE se l'esecuzione è andata a buon fine, altrimenti FALSE (e impostando il debugging avrete a schermo l'errore)
Nel caso in cui vada tutto bene avrete disponibili le seguenti variabili:

  • Page pagina corrente
  • Record record corrente
  • Pages numero di pagine
  • Records numero di record totali
  • RecordsPerPage numero di record per pagina
  • Recordset il recordset statico con la pagina richiesta

printNavigator(text,add,queryadd,printperpage)
Se non volete scrivere un navigatore fra le pagine potete utilizzare questa funzione che ne genera uno per voi
Lasciate text a NULL
in add potete indicare HTML da immettere sempre all'interno della form che verrà generata
queryadd è una stringa che verrà aggiunta a tutti i link (es: queryadd = "&amp;search=qualcosa")
printperpage è una flag (true/false) che indica se il valore "perpage" deve essere messo nei link (utile solo se lasciate a NULL l'argomento recordsPerPage in PAGINATE)

Reset()
Reimposta tutti i valori per una nuova paginazione (non è necessario poiché Paginate lo esegue)

About

ASP Class to simplify database (MDB & MySQL) interaction

Resources

License

Stars

Watchers

Forks

Packages

No packages published