💾 Archived View for magaz.hellug.gr › 24 › 04_perldbi › index.gmi captured on 2024-05-10 at 10:45:51. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-02-05)
-=-=-=-=-=-=-
Μιχάλης Καμπριάνης(mailto:kabrianis@hellug.gr) Ιουν 2000
Σε αυτό το τεύχος συνεχίζουμε την προσέγγιση στον προγραματισμό Perl για Databases μέσω του DBI interface που ξεκινήσαμε στο τεύχος Απριλίου.
Αυτή τη φορά θα ασχοληθούμε με απλά κολπάκια για καλύτερο προγραμματισμό, τα οποία δεν αναφέραμε στο εισαγωγικό άρθρο. Ξεκινάμε:
1.
Έλεγχος λαθών
Είχαμε πει στο προηγούμενο τεύχος ότι πρέπει ο προγραμματιστής να ελέγχει το exit status κάθε function που καλεί, για να δει αν πέτυχε ή όχι. Σε περίπτωση που δεν πέτυχε μπορεί να κάνει κάποιες δουλειές, αλλά συνήθως θέλει να σταματάει η εργασία εκεί. Γι αυτό το DBI παρέχει το RaiseError. Αμέσως μετά τη σύνδεση (ή και παράλληλα) μπορούμε να θέσουμε τη μεταβλητή RaiseError και τότε, σε κάθε error το πρόγραμμά μας θα σταματάει με ένα die.
Παράδειγμα 1 $dbh=DBI->connect('DBI:Pg:dbname=dbname user=dbuser password=dbpass'); $dbh->{RaiseError} = 1;
Η πρώτη γραμμή, απλά συνδέεται σε μία postgres database, στην βάση με όνομα dbname, με username dbuser και password dbpass. Η δεύτερη γραμμή θέτει τη μεταβλητή RaiseError όπως λέγαμε. `Αλλη μία μεταβλητή που μπορεί να τεθεί με αυτόν τον τρόπο, είναι η AutoCommit, για transactional databases. Αν δεν ξέρετε τι είναι transactional database, καλά θα κάνετε να διαβάσετε το manual της βάσης σας.
2.
Απ' ευθείας ανάθεση αποτελεσμάτων σε μεταβλητές
Εκτός από την παραδοσιακή μέθοδο που είδαμε στο προηγούμενο τεύχος, να τοποθετούμε δηλαδή τα αποτελέσματα σε ένα array (μία στήλη αποτελεσμάτων είναι αντίστοιχα ένα στοιχείο του array), μπορούμε να χρησιμοποιήσουμε την bind_columns για να αναθέσουμε τα αποτελέσματα σε ήδη ορισμένες μεταβλητές.
Παράδειγμα 2 $entoli = $dbh->prepare('SELECT phone,name FROM clients WHERE id=?'); $entoli->execute($num); $entoli->bind_columns(\$phone,\$name); $entoli->fetch;
Το $num καθώς και τα $phone και $name πρέπει προφανώς να τα έχουμε δηλώσει νωρίτερα. Προσοχή πρέπει να δοθεί στο ότι η bind_columns δίνεται μετά την execute. Επίσης όπως βλέπετε δεν χρησιμοποιούμε την fetchrow_array αλλά την σκέτη fetch για να τραβήξουμε τα στοιχεία από την βάση.
3.
Casting και πέρασμα παραμέτρων από πριν Μία άλλη μέθοδος που υποστηρίζει το DBI είναι η bind_param(). Αυτή δίνει εξ αρχής στην execute τις παραμέτρους που θα πάρει, δίνoντάς μας την δυνατότητα να κάνουμε και casting.
Παράδειγμα 2 $entoli = $dbh->prepare('SELECT phone,name FROM clients WHERE id=?'); $entoli->bind_param(1, $num, { TYPE => SQL_INTEGER }); $entoli->execute(); $entoli->bind_columns(\$phone,\$name); $entoli->fetch;
Σε αυτό το παράδειγμα πριν καλέσουμε την execute λέμε στο DBI ότι στο πρώτο placeholder (όπου placeholder είναι το ερωτηματικό, και το πρώτο βγαίνει από το 1 που είναι το πρώτο όρισμα της bind_param()) θα βάλει την τιμή $num και θα πει στην βάση μας ότι είναι τύπου Integer. Αυτό σε ορισμένες περιπτώσεις είναι χρήσιμο, αν και το σε ποιες ακριβώς, αφήνεται ως άσκηση στον αναγνώστη :-) Αν λοιπόν θέλουμε για οποιονδήποτε λόγο να κάνουμε casting, αυτή είναι η μέθοδος που πρέπει να ακολουθήσουμε.
4.
Αποθήκευση παραμέτρων σε hashed array
Αντί για την fetchrow_array και την fetch που είδαμε πιο πάνω, μπορούμε να χρησιμοποιήσουμε και την fetchrow_hashref() μέθοδο, για να τοποθετήσουμε τα αποτελέσματα που θα μας επιστρέψει η βάση σε ένα hash.
Για κάθε γραμμή αποτελεσμάτων που επιστρέφεται από την βάση, δημιουργείται ένα reference σε ένα array που περιέχει το field name σαν κλειδί και την τιμή του σαν value. Αν κάποιο value είναι Null, τότε επιστρέφεται με τιμή undef. Αυτό προσέξτε το γιατί σημαίνει ότι θα υπάρχει συνδυασμός κλειδί-τιμή στο hash που θα δημιουργηθεί (ενώ ίσως περίμενε κάποιος να μην υπάρχει καν αυτός ο συνδυασμός εφόσον η τιμή του είναι Null).
Αυτή η υλοποίηση δημιουργεί περισσότερο overhead στο πρόγραμμά μας απ' ότι η fetchrow_array και δεν είναι και πολύ μεταφέρσιμη μεταξύ των διαφορετικών βάσεων, συνεπώς αν δεν το χρειάζεστε, μην το χρησιμοποιήσετε.
5.
Πληροφορίες από την βάση
Μπορούμε να πάρουμε όλα τα αποτελέσματα του select μας με την μέθοδο dump_results() η οποία καλεί εσωτερικά την neat_list και τυπώνει τα αποτελέσματα.Aν δεν δώσουμε παραμέτρους, θα τυπώσει μέχρι 35 χαρακτήρες ($maxlen=35), μία γραμμή αποτελεσμάτων σε μία γραμμή του output ($lsep='\n'), χωρισμένες οι στήλες με κόμματα ($fsep=',') στο STDOUT ($fh). Όλα αυτά μπορούμε να τα αλλάξουμε με τις μεταβλητές που ανέφερα.
Η βάση μας δίνει επίσης πληροφορίες για:
* NUM_OF_FIELDS (integer)
Ο αριθμός των πεδίων που θα επιστρέψει το select που έχουμε κάνει prepare.
* NUM_OF_PARAMS (integer)
Ο αριθμός των παραμέτρων που περνάμε στην prepare (αυτά που λέγαμε για Placeholders).
* NAME (reference σε array)
Ένα reference σε array που περιέχει τα ονόματα των πεδίων. Υπάρχουν αντίστοιχα και οι NAME_lc και NAME_uc που επιστρέφουν τα ίδια στοιχεία σε LowerCase και UpperCase αντίστοιχα.
Όλες οι παραπάνω παράμετροι είναι βέβαια read_only.
Με αυτό το κείμενο τελειώσαμε την εισαγωγή στο DBI interface της perl. Διαβάστε πάλι την βιβλιογραφία από το προηγούμενο τεύχος και είστε έτοιμοι να ξεκινήσετε.